2010-04-23 18 views
10

Próbuję zapisać listę ogólnych obiektów na liście ogólnej, ale mam problem z jej deklaracją. Mój obiekt wygląda następująco:Ogólna lista składników generycznych

public class Field<T> 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public T Value { get; set; } 

    /* 
    ... 
    */ 
} 

Chciałbym utworzyć listę tych. Moim problemem jest to, że każdy obiekt na liście może mieć odrębny typ, tak, że lista zaludnionych może zawierać coś takiego:

{ Field<DateTime>, Field<int>, Field<double>, Field<DateTime> } 

Więc jak mogę oświadczyć, że?

List<Field<?>> 

(Chciałbym pozostać jak najbardziej bezpieczne, więc nie chcę używać ArrayList).

+0

Interesującym pomysłem jest "pozostać jak najbardziej bezpieczny", nie naruszając jednak koncepcji http://en.wikipedia.org/wiki/YAGNI? Zastanów się, w jaki sposób zamierzasz uzyskać dostęp do tej listy, czy naprawdę tego potrzebujesz? –

Odpowiedz

21

Jest to sytuacja, w której to może korzyści można mieć abstrakcyjną klasę bazową (lub interfejs) zawierający bity nierodzajową:

public abstract class Field 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
} 

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

    /* 
    ... 
    */ 
} 

Wtedy można mieć List<Field>. To wyraża wszystkie informacje, które faktycznie znasz o liście. Nie znasz typów wartości pól, ponieważ mogą one różnić się w zależności od pola.

+0

@Jon - Czy pierwsza klasa powinna być ogólna, czy po prostu prosta? – Giorgi

+1

@Giorgi, 'klasa abstrakcyjna Pole ' wygląda jak literówka. Mogłem to poprawić. –

+0

Nadal musi rzutować, aby uzyskać rzeczywisty typ wartości ... ale chodzi tu o jedyne rozwiązanie, które też mogę wymyślić, bez rzeczywistego typu "krotki". – tames

5

Być może zaimplementuj interfejs.

interface IField 
{ 
} 

class Field<T> : IField 
{ 
} 

...

List<IField> fields = new List<IField>() { new Field<int>(), new Field<double>() }; 
+0

To pozostawia go w tej samej pozycji, ponieważ IField nie zawiera typu (T). różni się od używania 'obiektu', ponieważ nadal będzie musiał rzutować, aby uzyskać wartość. – tames

+0

@tames, jest w lepszej pozycji, ponieważ elementy jego listy muszą implementować IField (lub dziedziczyć z Fielda, na przykładzie Jona). lista jest jeszcze silniej wpisana niż lista obiektów. –

+0

@anthony ...Zgadzam się i użyłem zarówno interfejsu, jak i rozwiązań klasy podstawowej. – tames

5

Nie można zadeklarować listę typów generycznych nie znając typu rodzajowego w czasie kompilacji.

Można zadeklarować List<Field<int>> lub List<Field<double>>, ale nie ma innego wspólny typ bazowy dla Field<int> i Field<double> niż object. Zatem jedynym List<T>, który mógłby pomieścić różne rodzaje pól, byłby List<object>.

Jeśli chcesz mieć bardziej szczegółowy typ dla tej listy, musisz uczynić klasę Field<T> dziedziczącą klasę lub implementującą interfejs. Następnie możesz użyć tego dla rodzaju ogólnego na liście.