2009-02-18 4 views
3

J'ai une classe qui correspond à un champ dans une base de données. La classe se soucie uniquement du nom du champ et de son type .NET associé. Le type peut être une chaîne, int, datetime, etc.Listes génériques C#

class Foo() 
{ 
    string Name { get; set; } 
    Type FooType { get; set; } 
} 

J'ai une autre classe qui hérite de Foo qui ajoute une propriété pour une valeur. En ce moment je stocke la valeur en tant qu'objet et utilise une instruction switch pour encadrer la valeur basée sur les classes de base FooType. Y a-t-il moyen de mettre en œuvre ceci avec des génériques pour donner le type de sécurité pour les valeurs?

Édition: J'ai fait en sorte que la clé soit en gras. Lorsque vous déclarez une liste, dites Foo, il faut un type. Si je faisais cela par rapport à des classes personnalisées, je créerais et interfacerais et j'utiliserais cela. Cependant, ici, j'utilise int, string, DateTime, etc. Int est une struct, string est un objet, donc un objet Foo <> ne fonctionne pas pour les deux.

Répondre

8

Définir votre classe comme ceci:

class Foo<T> : IFoo 
{ 

    public Foo(string name) 
    { 
     Name = name; 
    } 

    string Name { get; set; } 
    T Value {get; set;} 
    Type FooType { get { return typeof(T); } } 
} 

Vous pouvez ensuite définir le IFoo d'interface:

string Name { get; set; } 
Type FooType { get; set; } 

Et déclarer une liste comme:

List<IFoo> list = new List<IFoo>(); 
+0

Cela ressemble à l'implémentation la plus complète, la plus précise et la plus propre. Je suis en train de l'essayer. – blu

1

J'utiliserais une interface plutôt qu'un héritage de classe générique sur cela.

Modifier: Pour clarifier. J'utiliser une interface pour Foo, et une classe générique pour FooWithStuff:

public interface IFoo 
{ 
    string Name{get;set;} 
    Type FooType{get;set;} 
} 

public class FooWithStuff<T>:IFoo 
{ 
    T Value {get;set;} 
} 
+0

Pourquoi garderiez-vous le type sur l'interface, il n'est pas nécessaire pour la conversion? – blu

+0

Je suppose que je manque le point. @divo, ya que j'ai supposé beaucoup à ce sujet. –

2

Si vous voulez ajouter de la valeur à Foo et ont Foo être que vous pourriez faire générique ...

class Foo<T> 
{ 
    T Value {get; set;} 
} 

Foo<int> myFoo = new Foo<int>(); 
myFoo.Value = 7; 
+0

Mais cela ne remplirait pas la contrainte supplémentaire que T est le même type que FooType? –

+0

Vous ne stockez plus FooType: à la place, vous pouvez appeler Foo .GetType(). GetGenericArguments [0] –

+0

Ou créer une propriété qui renvoie: public Type FooType {get {return typeof (T); }} – configurator

9
class Foo 
{ 
    public string Name { get; set; } 
    public Type Type { get; set; } 
} 

class Bar<T> : Foo 
{ 
    public T Value { get; set; } 

    public Bar() 
    { 
     base.Type = typeof(T); 
    } 
} 
0

Oui, en fait, vous pouvez faire disparaître votre héritage, tout simplement ..

public class Foo<T> 
{ 
    public string Name {get;set;} 
    public T Value {get;set;} 
    public Type FooType 
    { 
    get 
    { 
     return typeof(T); 
    } 
    } 
} 

Notez également, en utilisant LINQ, vous pouvez simplement extraire les types que vous avez besoin la liste directement, donc si vous êtes simplement intéressé par les champs de chaîne pour une raison quelconque vous pourriez ...

List<object> list = getAllmyFoos(); 
foreach(Foo<string> sfoo in list.OfType<Foo<string>>()) 
{ 
    ...blah 
} 

Edit: Ajouté FooType.

+0

Le problème est lorsque je déclare la liste, il a besoin d'un type, et il stocke les ints, chaînes, et datetimes, etc – blu

+0

Bien sûr. Si vous en avez besoin, vous en avez besoin. –

-2

Je conseillerais à l'aide 2 interfaces:

public interface IFoo 
{ 
    string Name {get; } 
    Type Type { get; } 
    object Value {get; set;} 
} 

public interface IFoo<T> : IFoo 
{ 
    T Value {get; set} 
} 

ensuite l'appliquer:

public class Foo<T> : IFoo<T> 
{ 
    private T value; 
    public Foo(string name, T value) 
    { 
    this.name = name; 
    this.value = value; 
    } 

    public string Name { get { return name; } } 
    public Type Type { get { return typeof(T); } } 
    public T Value 
    { 
     get { return value; } 
     set { value = value; } 
    } 

    object IFoo.Value 
    { 
     get { return value; } 
     set { value = (T)value; } // can check type before 
    } 
} 

De cette façon, vous pouvez utiliser l'interface IFoo facilement dans un contexte non générique aussi.