2009-11-26 9 views
3

Question du débutant: Comment implémenter une liste générique List<Item> renvoyer des articles avec une propriété nommée Données mais renvoyant des types différents pour différentes sous-classes? J'ai commencé à construire la hiérarchie suivante, mais cela ne mène pas au but.Le même nom de propriété mais un type de retour différent dans une liste générique

abstract class Item 
abstract class ItemGeneric<TData> : Item 
class ItemText : ItemGeneric<string> 
class ItemImage : ItemGeneric<Image> 

créer un groupe d'instances de classes libelléLigne et ItemImage et les ajouter à une liste List<Item> générique. Cependant, une fois que je parcours la liste et que je veux récupérer la propriété Data, elle n'est pas accessible car (évidemment) elle a été implémentée uniquement au niveau de la hiérarchie des classes ItemGeneric<TData> et non dans la classe Item.

Je voudrais résoudre ce problème sans utiliser System.Object pour éviter la coulée.

Existe-t-il un modèle commun pour résoudre ce problème?

Répondre

1

Je ne suis pas sûr à 100% si je comprends le problème.

J'utilise généralement une interface avec une propriété typées:

interface IUntypedItem 
{ 
    object UntypedData {get; } 
} 

interface IItem<T> : IUntypedItem 
{ 
    T Data {get; set;} 
} 

class abstract ItemGeneric<T> : IItem<T> 
{ 
    T Data { get; set; } 
    object UntypedData { get { return Data; }} 
} 

class ItemText : ItemGeneric<string> 
{ 

} 

alors vous pouvez avoir alist de UntypedItems

List<IUntypedItem> list; 
foreach (IUntypedItem item in list) 
{ 
    // use item.UntypedData 
    // or downcast to use typed property 
} 

Vous ne pouvez pas éviter la coulée ou des objets lorsque vous souhaitez traiter différents types dans la même liste. Vous pouvez juste clarifier ce que vous faites.

0

Quelque chose comme ça?

public class ItemGeneric<T> { 

    private List<T> data; 

} 

public class ItemText : ItemGeneric<String> { ... } 

public class ItemImage : ItemGeneric<Image> { ... } 

En Java, vous pouvez définir la superclasse comme un type générique T, je ne sais pas comment cela fonctionne en C#

public class ItemGeneric<T extends IData> { 

private List<T> data; 
} 
0

Voici comment vous créez une fonction dans BaseClass qui retourne la collection de DerivedTypes lorsqu'il est appelé depuis un objet de type derivedclass, pas de magie juste Generics. Cet exemple parle de HashSet, dans votre cas, il pourrait être n'importe quel type que vous voulez.

//**The BaseClass** 
public class BaseClass<T> 
    where T : BaseClass<T> 
{ 
    public HashSet<T> GetHashSet() 
    { 
     HashSet<T> hSet = new HashSet<T>(); 
     //create a HashSet<T> 
     //do some work 
     //and return; 
     return hSet; 
    } 
} 

//**The Derived Class** 
public class DerivedClass : BaseClass<DerivedClass> 
{ 
    //you have the method inherited. 
} 
1

Si vous exécutez certaines fonctionnalités sur des données typées en dehors de la classe conteneur, vous devez connaître le type d'avance.

Pas agréable:

foreach (Item item in list) 
{ 
    ItemGeneric<int> intItem = item as ItemGeneric<int>; 
    if (intItem != null) 
    { 
     //do stuff 
    } 
} 

Vous pouvez résoudre ce problème en déplaçant la fonctionnalité dans la classe contenant les données.

(voir encapsulation)

Ainsi, vous pouvez utiliser votre liste comme ceci:

foreach (Item item in list) 
{ 
    item.DoStuff(); 
} 

qui signifie que vous aurez besoin d'un DoStuff sur votre classe d'objet:

public abstract class Item 
{ 
    public abstract void DoStuff(); 
} 

. .et peut implémenter cela sur votre ItemGeneric:

public class ItemGeneric<T> : Item 
{ 
    public T Data { get; set; } 

    public override void DoStuff() 
    { 
     //do generic typed stuff here 
     Console.WriteLine(Data); 
    } 
} 
Questions connexes