我有这样的设置:
abstract class Foo {}
class Bar : Foo {}
以及此形式的其他方法:
void AddEntries(List<Foo>) {}
我试图使用Bar
List<Bar> barList = new List<Bar>()
AddEntries(barList);
但这给了我错误:
无法从List&lt; Bar&gt;转换列出&lt; Foo&gt;
还有这个问题吗?我需要使用抽象类来保持方法定义。
答案 0 :(得分:65)
您可以将AddEntries
通用并将其更改为此
void AddEntries<T>(List<T> test) where T : Foo
{
//your logic
}
请查看Constraints on Type Parameters以获取更多信息。
答案 1 :(得分:60)
请读取Covariance and Contravariance in Generics from docs.microsoft.com,特别是&#34;带有协变类型参数的通用接口&#34; 将涵盖您正在工作的方案用。
简而言之,如果您(可以)将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):
协方差:允许您使用比最初指定的派生类型更多的派生类型。
答案 2 :(得分:43)
由于一个简单的原因,这是不允许的。假设以下编译:
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
{
}