2016-02-24 4 views
0

У меня есть класс, как:C# Список неопределенных общих классов?

class GClass<T1, T2> {} 

реализаций:

class CClass1<String, String> {} 
class CCLass2<String, Double> {} 

На моем C# код, который я должен был бы определить объект, как этот List<GClass<T1,?>.

Возможно ли это?

С другой стороны, я проверил с List<GClass<String, Object>>, однако я не могу добавить объект, как это:

List<GClass<String, Object>> list = new List<GClass<String, Object>>(); 
CClass1 c1 = new CClass1(); 
list.Add(c1); 

Компилятор сбрасывает мне ошибку компиляции.

EDIT

Я проверил с ним:

public interface IViz<T, TQuery, out TOut> 
{ 
    Configuration.IVizConfiguration<T> VizConfiguration { get; } 
    IList<TOut> SelectedValues { get; } 

    IEnumerable<TQuery> generate(IEnumerable<T> search); 
    Expression<Func<T, bool>> generateExpression(Object selectedVizValue); 
    IEnumerable<Expression<Func<T, bool>>> generateExpressions(IEnumerable<Object> selectedVizValues); 
} 

Однако компилятор говорит мне:

Ошибка 3 Invalid дисперсия: Параметр типа 'Tout' должен быть инвариантно действующий на 'UI.Forms.SearchTool.Visualization.IViz.SelectedValues'. «TOUT» ковариантен. D: \ проекты \ живой \ клиентов \ NetClient \ UI \ Forms \ SearchTool \ Визуализация \ IViz.cs 8 42 UI

+0

Можете ли вы описать ошибку компиляции? – badikumar

+0

'CClass1 {}' что такое 'CClass1' и' CClass2'? – Ian

ответ

5

Вы можете сделать это поведение, добавив интерфейс и использовать общий модификатор out на свой параметр типа , что делает его ковариантным.

От documentation, out (Generic Modifier):

Для параметров универсального типа, то из ключевых слов указывает, что параметр типа ковариантен. Вы можете использовать ключевое слово out в общих интерфейсах и делегатах.

Covariance позволяет использовать более производный тип, чем тот, который задан общим параметром. Это позволяет неявное преобразование классов, которые реализуют варианты интерфейсов и неявное преобразование типов делегатов. Ковариантность и контравариантность поддерживаются для ссылочных типов, но они не поддерживаются для типов значений.

Пример:

public interface GInterface<T1, out T2> {} 
public class GClass<T1, T2> : GInterface<T1, T2> {} 

Использование:

List<GInterface<String, Object>> list = new List<GInterface<String, Object>>(); 
GClass<string, string> c1 = new GClass<string, string>(); 
list.Add(c1); 
+0

Я проверил ваш подход.Я не знаю, почему, однако компилятор сообщает мне об ошибке. Взгляните на вопрос. Благодаря! – Jordi

+0

Вы получаете эту ошибку, потому что 'IList' не ковариант, вы можете изменить его для' IEnumerable', который является ковариантным. –

4

Нет, вы не можете сделать это, но вы можете определить общий интерфейс, имеющий только один из общих типов:

interface IClass<T> { } 
class GClass<T1, T2> : IClass<T1> { } 

class CClass1 : GClass<string, object> { } 
class CClass2 : GClass<string, double> { } 

Затем вы можете создать список общего интерфейса:

List<IClass<String>> list = new List<IClass<String>>(); 
list.Add(new CClass1()); 
list.Add(new CClass2()); 
Смежные вопросы