2010-01-15 17 views
5

Cada elemento tiene una interfaz, IItem. Además de esto, existe una interfaz conocida como IDrawableItem que hereda de Item.Casting y herencia de interfaz

El siguiente código intenta dibujar un elemento dibujable, pero no puede, ya que la colección almacena esta clase acepta solo IItem. Puede agregar cualquier cosa que herede de IItem a esta clase, pero usar otros métodos solo se puede lograr mediante casting.

foreach (var item in Items) { 
    item.Draw();    // The casting would go here. 
} 

sé cómo lanzar, as etc ... pero es esto aceptable? ¿Es una mejor práctica?

Solo me pregunto si hay otras formas de manejar estos escenarios.

+0

El código siguiente trata de dibujar un elemento dibujable, pero no puede, ya que la colección que almacena esta clase solo acepta IItem. - ¿POR QUÉ? Cuéntanos un poco sobre el diseño. ¿Puedes cambiarlo? –

+0

El código de Jason te sacará de tu dilema. El problema es si este es el diseño correcto para sus objetos, y eso es realmente difícil de decir a partir de 2 líneas de descripción. – hackerhasid

+0

¿Quizás use una colección que almacene IDrawbleItem s en su lugar? –

Respuesta

11

Uso Enumerable.OfType para extraer sólo aquellos elementos de Items que implementan IDrawableItem:

foreach(var item in Items.OfType<IDrawableItem>()) { 
    item.Draw(); 
} 

Para abordar la cuestión de que Nanook pidió en los comentarios del código anterior, probablemente se traduce en un código equivalente a la siguiente:

foreach(var item in Items) { 
    if(item is IDrawableItem) { 
     ((IDrawable)item).Draw(); 
    } 
} 

Por supuesto, en realidad no es un iterador detrás de las escenas que se ve algo como esto:

public static IEnumerable<T> OfType<T>(this IEnumerable<TSource> source) { 
    if(source == null) { 
     throw new ArgumentNullException("source"); 
    } 
    foreach(TSource item in source) { 
     if(item is T) { 
      yield return (T)item; 
     } 
    } 
} 

Entonces, lo que esto muestra es que probablemente solo iteremos a través de Items una vez. Por supuesto, no hay ningún requisito de que OfType se implemente como el anterior, pero esto es lo más sensato.

+0

¿Este ejemplo realmente realiza 2 bucles? 1 para obtener IDrawableItems y otro para recorrerlos y llamar a Draw. Si es así, esto no es muy eficiente. – Nanook

+2

No, transmite los resultados. –

+0

Nop, no es así. Todos los métodos Linq.Enumerable se implementan mediante el uso de un Enumerador personalizado. El código anterior se traduciría en algo así como foreach (var item en los ítems) {if item is IDrawableItem yield return item como IDrawableItem; } – herzmeister

1

dos soluciones alternativas:

  • mantener el dibujables en una recogida selectiva.
  • Agregue el método DrawIfPossible() al IItem. IDrawableItem debe anularlo para llamar al Draw(), otros implementadores IItem() deben tener una implementación vacía.

Las consultas de tipo explícito se consideran un signo de que puede haber algún problema con el diseño.

+0

Como ya he dicho, este es un prototipo rápido que probablemente cambie. Aunque estoy de acuerdo acerca de su último punto con respecto al diseño. – Finglas

+0

No fue una crítica. Hay casos en que es necesaria la consulta de tipo. Cortes rápidos, marcos que pasan objetos como 'ICastItDownAsNeeded', etc. –

Cuestiones relacionadas