我的课程如下:
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);
编译器向我转储编译错误。
修改
我已经用它测试过:
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方差无效:类型参数&#39; TOut&#39;必须在&#39; UI.Forms.SearchTool.Visualization.IViz.SelectedValues&#39;上无条件有效。 &#39; TOUT&#39;是协变的。 D:\ projects \ living \ clients \ NetClient \ UI \ Forms \ SearchTool \ Visualization \ IViz.cs 8 42 UI
答案 0 :(得分:5)
您可以通过添加接口并在类型参数上使用泛型修饰符out
来实现此行为,从而使其协变。
来自documentation, out (Generic Modifier):
对于泛型类型参数,out关键字指定type参数是协变的。您可以在通用接口和委托中使用out关键字。
协方差使您可以使用比泛型参数指定的派生类型更多的派生类型。这允许隐式转换实现变体接口的类和委托类型的隐式转换。参考类型支持协方差和逆变,但值类型不支持它们。
示例:
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);
答案 1 :(得分: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());