考虑以下类(继承树):
public class A {}
public class B: A {}
这个方法:
public IList<A> MyMethod(){
IList<B> result = new List<B>();
//add some items to result
return result;
}
编译器不满意。错误是Cannot convert expression type IList<B> to return type IList<A>
。我该如何解决这个问题?换句话说,如何指定MyMethod
将返回IList<T>
T
T
,其中A
可以是从A
继承的任何内容或{{1}}的实例本身?
答案 0 :(得分:4)
您要求的内容是不可能的,因为IList<T>
不支持差异 - 您无法在期望IList<B>
的任何地方使用IList<A>
。为了提出解决方案,你必须解释你想要的更多细节。
可能的解决方案是:
public IList<A> MyMethod(){
IList<A> result = new List<A>();
//add some items to result
return result;
}
或者
public IEnumerable<A> MyMethod(){
IList<B> result = new List<B>();
//add some items to result
return result;
}
答案 1 :(得分:2)
您无法转换IList&lt; B&gt;到IList&lt; A&gt;,即使B继承自A.否则,用户可能会尝试将不是B的A实例添加到列表中。
public void Example(){
IList<B> listB = new List<B>();
IList<A> listA = listB;
listA.Add(new A()); // Can't insert A into a list of B
}
你能否返回IEnumerable&lt; A&gt;而不是IList&lt; A&gt;? IEnumerable的&LT a取代;与IList&lt; A&gt;不同,它是协变的。
答案 2 :(得分:1)
如何指定MyMethod将返回T的IList,其中T可以是从A继承的任何东西还是A本身的实例?
您可以声明它返回IList<A>
。为什么?考虑到B
继承自A
- B
的每个项目都可以在所请求的类型为A
的地方传递。
通过继承,Liskov替换原则或方法方差称它为多态,名称无关紧要。重要的是以下工作(在LinqPad上测试):
public class A {}
public class B: A {}
public IList<A> MyMethod()
{
var result = new List<A>();
//add some items to result
result.Add(new B());
return result;
}
事实上,您可以告诉您要返回IList<TA>
并请求一些派生类型(TB
,TC
...)来填充它。这是正确的,以下示例也适用(在LinqPad上测试):
void Main()
{
MyMethod<A, B, C>();
}
public class A {}
public class B: A {}
public class C: A {}
public IList<TA> MyMethod<TA, TB, TC>()
where TB : TA, new()
where TC : TA, new()
where TA : class
{
var result = new List<TA>();
//add some items to result
result.Add(new B() as TA);
result.Add(new C() as TA);
return result;
}
或者如果你想保留一个特定的基类型(假设你想要返回IList<A>
但它实际上包含从A
派生的类的项,那么你可以这样做:
void Main()
{
MyMethod<B, C>();
}
public class A {}
public class B: A {}
public class C: A {}
public IList<A> MyMethod<T1, T2>()
where T1 : A, new()
where T2 : A, new()
{
var result = new List<A>();
//add some items to result
result.Add(new T1() as A);
result.Add(new T2() as A);
return result;
}
好的,如果你真的想说它返回IList<T>
where T : A
。然后说出来!
void Main()
{
MyMethod<B>();
}
public class A {}
public class B: A {}
//public class C: A {} //Even if I don't add that class
public IList<T> MyMethod<T>()
where T : A, new()
{
var result = new List<T>();
//add some items to result
result.Add(new T());
return result;
}
是的,那个人不能返回T
类型的项目和A
类型的项目的混合,因为它表示它返回IList<T>
而不是{{1}类型的每个项目}也是A
类型的项目。
看看你的代码:
T
当您说要返回public IList<A> MyMethod(){
IList<B> result = new List<B>();
//add some items to result
return result;
}
时,您正试图返回IList<B>
。让我们假设它有效...那么你的方法的调用者会发生什么?我们来看看:
IList<A>
DFTBA!