Considere si será común tener colecciones de objetos con diferentes combinaciones de habilidades, y si el código puede querer realizar una acción sobre esos elementos, dentro de una colección, que lo soportan . Si es así, y si hubiera un "comportamiento predeterminado" sensible para los objetos que no tienen soporte útil para alguna acción, puede ser útil tener interfaces implementadas por una amplia gama de clases, no solo aquellas que pueden comportarse de manera útil.
Por ejemplo, supongamos que solo unos pocos tipos de criaturas pueden tener Woozles, y uno quiere que tales criaturas tengan una NumerOfWoozlespropiedad. Si dicha propiedad estuviera en una interfaz que solo fueran implementadas por criaturas que pueden tener Woozles, entonces el código que quería encontrar el número total de Woozles en poder de una colección de criaturas de tipos mixtos tendría que decir algo como:
int total = 0;
foreach (object it in creatures)
{
IWoozleCountable w = trycast(it, IWoozleCountable);
if (w != null) total += w.WoozleCount;
}
Sin embargo, si WoozleCount fuera miembro de Creature / ICreature, a pesar de que pocos subtipos anularían la implementación de WoozleCount predeterminada de Creature que siempre devuelve cero, el código podría simplificarse para:
int total = 0;
foreach (ICreature it in creatures)
total += it.WoozleCount;
Si bien algunas personas pueden irritarse ante la idea de que cada Criatura implemente una propiedad WoozleCount que realmente solo es útil para unos pocos subtipos, la propiedad sería significativa para todos los tipos, ya sea que sea útil o no con elementos que se sabe que son de esos tipos, y consideraría que la interfaz del "fregadero de la cocina" tiene menos olor a código que el operador trycast.
IEnumerable,IEquatable, etc.