2012-05-15 16 views
7
public abstract Column<T> 
{ 
    private T Value {get;set;}  

    public abstract string Format(); 

} 

public class DateColumn : Column<DateTime> 
{ 
    public override string Format() 
    { 
     return Value.ToString("dd-MMM-yyyy"); 
    } 
} 

public class NumberColumn : Column<decimal> 
{ 
    public override string Format() 
    { 
     return Value.ToString(); 
    } 
} 

Problemem, który mam, jest dodanie ich do ogólnej kolekcji. Wiem, że to możliwe, ale jak mogę przechowywać wiele typów w kolekcji itp.Różne generyczne T w tej samej kolekcji

IList<Column<?>> columns = new List<Column<?>() 

Byłbym wdzięczny za wszelkie porady dotyczące osiągnięcia tego celu. Celem jest posiadanie różnych typów kolumn przechowywanych na tej samej liście. Warto wspomnieć, że używam NHibernate i discriminator do załadowania odpowiedniego obiektu. W końcu wartość musi mieć typ klasy.

Dziękujemy za pomoc z góry.

+0

Jestem mylić o tym punkcie. Generics pomaga w bezpieczeństwie typu. Niezależnie od tego, jeśli naprawdę chciałeś to zrobić, czy nie mógłbyś wypełnić swojej listy Kolumną ? – Killnine

+0

Nie, to by nie działało, próbowałem używać kolumny Myślę, że problem tkwi w tym, że wartość zdefiniowana przez polimorfizm, a następnie jest w stanie przechowywać to w zbiorze. Używam dyskryminatora do ładowania różnych typów kolumn. – Jonathan

+0

Istnieje już tylko kilka (http://stackoverflow.com/q/3215402/590790) [duplikatów] (http://stackoverflow.com/q/3777057/590790) tego pytania. Oprócz "podstawowego typu" rozwiązania [opublikowanego tutaj przez JaredPar] (http://stackoverflow.com/a/10606974/590790), chciałbym zaproponować [podążanie za wzorcem adaptera, aby stworzyć nietypowe opakowanie do ten cel] (http://stackoverflow.com/a/34417767/590790), tak aby zasada zastępowania Liskov nie została złamana. –

Odpowiedz

13

Aby kolumny mogły być przechowywane razem w List<T>, muszą mieć wspólny typ podstawowy. Najbliższa wspólna klasa bazowa DateColumn i NumberColumn to object. Żadne nie pochodzi od Column<T>, ale zamiast tego specyficzne i różne tworzenie instancji Column<T>.

Jednym z rozwiązań jest tu wprowadzenie nierodzajową Column typ który Column<T> wynika z przechowywania i że w List

public abstract class Column { 
    public abstract object ValueUntyped { get; } 
} 

public abstract class Column<T> : Column { 
    public T Value { get; set; } 
    public override object ValueUntyped { get { return Value; } } 
} 

... 

IList<Column> list = new List<Column>(); 
list.Add(new DateColumn()); 
list.Add(new NumberColumn()); 
+5

Możesz również rozważyć interfejs zamiast klasy bazowej. –

2

Produkty generyczne dotyczą wyłącznie określania typu. Jeśli chcesz używać typów dynamicznych, użyj zamiast tego klasycznego ArrayList.

+2

W tym przypadku nie wierzę, że OP chce dynamicznego pisania, ale zamiast tego chce skorzystać z typów bazowych i zachowania polimorficznego. – JaredPar

+0

Tak, masz rację. @JaredPar Potrzebuję parsować wartości i próbować odgadnąć, czym jest obiekt. trudny. – Jonathan

+2

Masz rację, I + 1ed twoją szczegółową odpowiedź. – Pol

3

Prawdopodobnie ma sens wywodzić się z nietypowej klasy Column, która opakowuje tyle nietypowego wspólnego interfejsu kolumny ..., aby zadeklarować swoją listę jako List<Column>.

+1

... a co @JaredPar powiedział ... – spender

Powiązane problemy