简体   繁体   English

无法从List <Bar>转换为List <Foo>

[英]Cannot convert from List<Bar> to List<Foo>

I have a set up like this: 我有这样的设置:

abstract class Foo {}
class Bar : Foo {}

and a method elsewhere of this form: 和其他形式的方法:

void AddEntries(List<Foo>) {}

I am trying to call this method using a list of objects of type Bar 我试图使用Bar类型的对象列表来调用此方法

List<Bar> barList = new List<Bar>()
AddEntries(barList);

but this gives me the error: 但这给了我错误:

cannot convert from List<Bar> to List<Foo> 无法从List <Bar>转换为List <Foo>

Is there anyway around this problem? 反正这个问题呢? I Need to keep the method definition using the abstract class. 我需要使用抽象类来保持方法定义。

You could make your AddEntries generic and change it to this 您可以将AddEntries通用并将其更改为此

void AddEntries<T>(List<T> test) where T : Foo
{
    //your logic 
}

Have a look at Constraints on Type Parameters for further information. 有关更多信息,请查看类型参数约束

Have a read of Covariance and Contravariance in Generics from docs.microsoft.com as this, particularly the section "Generic Interfaces with Covariant Type Parameters" will cover off the scenario that you're working with. 从docs.microsoft.com中读取泛型中协方差和逆变,因此,特别是“使用协变类型参数的通用接口”部分将涵盖您正在使用的场景。

In short, if you (can) change the signature of your AddEntries method to: 简而言之,如果您(可以)将AddEntries方法的签名更改为:

static void AddEntries(IEnumerable<Foo> entries)

(Note the use of IEnumerable<Foo> instead of List<Foo> ) you'll be able to do what you're looking to do. (注意使用IEnumerable<Foo>而不是List<Foo> )你将能够做你想做的事情。

The specific difference here is that the IEnumerable<T> and List<T> are declared differently: 这里的具体区别是IEnumerable<T>List<T>的声明方式不同:

public interface IEnumerable<out T> : IEnumerable
public class List<T> : IList<T>, ... ...

The difference that matters is the out in the declaration of IEnumerable<T> which indicates that it is covariant which means (with the definition taken from docs.microsoft.com): 事项所不同的是out在声明IEnumerable<T>这表示它是协变 ,这意味着(与来自docs.microsoft.com采取的定义):

Covariance : Enables you to use a more derived type than originally specified. 协方差 :使您可以使用比最初指定的派生类型更多的派生类型。

This is not allowed for a simple reason. 由于一个简单的原因,这是不允许的。 Assume the below compiles: 假设以下编译:

AddEntries(new List<Bar>());

void AddEntries(List<Foo> list)
{
   // list is a `List<Bar>` at run-time
   list.Add(new SomethingElseDerivingFromFoo()); // what ?!
}

If your code would compile, you have an unsafe addition (which makes the whole generic lists pointless) where you added SomethingElseDerivingFromFoo to actually a List<Bar> (runtime type). 如果你的代码会编译,你有一个不安全的添加(这使整个通用列表毫无意义)你将SomethingElseDerivingFromFoo添加到实际的List<Bar> (运行时类型)。

To solve your problem, you can use generics: 要解决您的问题,您可以使用泛型:

void AddEntries<T>(List<T> list) where T:Foo
{

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM