Considera se sarà comune avere raccolte di oggetti con diverse combinazioni di abilità e se il codice potrebbe voler eseguire un'azione su quegli oggetti, all'interno di una raccolta, che lo supportano . In tal caso, e se ci fosse un "comportamento predefinito" ragionevole per gli oggetti che non hanno un supporto utile per alcune azioni, può essere utile avere interfacce implementate da una vasta gamma di classi, non solo quelle che possono comportarsi in modo utile.
Ad esempio, supponiamo che solo pochi tipi di creatura possano avere Woozles e che si desideri che tali creature abbiano una NumerOfWoozles
proprietà. Se una tale proprietà fosse in un'interfaccia implementata solo da creature che possono avere Woozles, allora il codice che voleva trovare il numero totale di Woozles posseduto da una collezione di creature di tipi misti dovrebbe dire qualcosa del tipo:
int total = 0;
foreach (object it in creatures)
{
IWoozleCountable w = trycast(it, IWoozleCountable);
if (w != null) total += w.WoozleCount;
}
Se, tuttavia, WoozleCount fosse un membro di Creature / ICreature, anche se pochi sottotipi sovrascriverebbero l'implementazione WoozleCount predefinita di Creature che restituisce sempre zero, il codice potrebbe essere semplificato per:
int total = 0;
foreach (ICreature it in creatures)
total += it.WoozleCount;
Mentre alcune persone potrebbero lamentarsi dell'idea che ogni Creatura implementi una proprietà WoozleCount che sia davvero utile solo per alcuni sottotipi, la proprietà sarebbe significativa per tutti i tipi, indipendentemente dal fatto che sarebbe utile con oggetti noti per essere di quei tipi, e considererei l'interfaccia del "lavello della cucina" come un odore di codice inferiore rispetto all'operatore trycast.
IEnumerable
,IEquatable
e così via