[英]C# List<Interface>: why you cannot do `List<IFoo> foo = new List<Bar>();`
[英]Cannot convert from List<Bar> to List<Foo>
我有这样的设置:
abstract class Foo {}
class Bar : Foo {}
和其他形式的方法:
void AddEntries(List<Foo>) {}
我试图使用Bar
类型的对象列表来调用此方法
List<Bar> barList = new List<Bar>()
AddEntries(barList);
但这给了我错误:
无法从List <Bar>转换为List <Foo>
反正这个问题呢? 我需要使用抽象类来保持方法定义。
您可以将AddEntries
通用并将其更改为此
void AddEntries<T>(List<T> test) where T : Foo
{
//your logic
}
有关更多信息,请查看类型参数约束 。
从docs.microsoft.com中读取泛型中的协方差和逆变,因此,特别是“使用协变类型参数的通用接口”部分将涵盖您正在使用的场景。
简而言之,如果您(可以)将AddEntries
方法的签名更改为:
static void AddEntries(IEnumerable<Foo> entries)
(注意使用IEnumerable<Foo>
而不是List<Foo>
)你将能够做你想做的事情。
这里的具体区别是IEnumerable<T>
和List<T>
的声明方式不同:
public interface IEnumerable<out T> : IEnumerable
public class List<T> : IList<T>, ... ...
的事项所不同的是out
在声明IEnumerable<T>
这表示它是协变 ,这意味着(与来自docs.microsoft.com采取的定义):
协方差 :使您可以使用比最初指定的派生类型更多的派生类型。
由于一个简单的原因,这是不允许的。 假设以下编译:
AddEntries(new List<Bar>());
void AddEntries(List<Foo> list)
{
// list is a `List<Bar>` at run-time
list.Add(new SomethingElseDerivingFromFoo()); // what ?!
}
如果你的代码会编译,你有一个不安全的添加(这使整个通用列表毫无意义)你将SomethingElseDerivingFromFoo
添加到实际的List<Bar>
(运行时类型)。
要解决您的问题,您可以使用泛型:
void AddEntries<T>(List<T> list) where T:Foo
{
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.