我有两个类:一个基类(Animal)和一个从它派生的类(Cat).Base类包含一个虚拟方法Play,它将List作为输入参数.这样的东西
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication9
{
class Animal
{
public virtual void Play(List<Animal> animal) { }
}
class Cat : Animal
{
public override void Play(List<Animal> animal)
{
}
}
class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
cat.Play(new List<Cat>());
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我编译上面的程序时,我得到以下错误
Error 2 Argument 1: cannot convert from 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
反正有没有完成这个?
Eri*_*ert 53
你不能这样做的原因是因为列表是可写的.假设它是合法的,看看出了什么问题:
List<Cat> cats = new List<Cat>();
List<Animal> animals = cats; // Trouble brewing...
animals.Add(new Dog()); // hey, we just added a dog to a list of cats...
cats[0].Speak(); // Woof!
Run Code Online (Sandbox Code Playgroud)
好吧,我的猫,这是坏事.
您想要的功能称为"通用协方差",C#4支持已知安全的接口.IEnumerable<T>没有任何方法可以写入序列,所以它是安全的.
class Animal
{
public virtual void Play(IEnumerable<Animal> animals) { }
}
class Cat : Animal
{
public override void Play(IEnumerable<Animal> animals) { }
}
class Program
{
static void Main()
{
Cat cat = new Cat();
cat.Play(new List<Cat>());
}
}
Run Code Online (Sandbox Code Playgroud)
这将工作,C#4,因为List<Cat>可转换为IEnumerable<Cat>,这是转换为IEnumerable<Animal>.Play无法IEnumerable<Animal>将狗添加到实际上是猫列表的东西中.
Ant*_*ram 15
你可以做一些事情.一个例子是将列表的元素强制转换为Animal
使用你的代码:
cat.Play(new List<Cat>().Cast<Animal>().ToList());
Run Code Online (Sandbox Code Playgroud)
另一个是制作Animal通用,所以cat.Play(new List<Cat>());会起作用.
class Animal<T>
{
public virtual void Play(List<T> animals) { }
}
class Cat : Animal<Cat>
{
public override void Play(List<Cat> cats)
{
}
}
class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
cat.Play(new List<Cat>());
}
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是不制作Animal通用,但Play方法和约束T : Animal
class Animal
{
public virtual void Play<T>(List<T> animals) where T : Animal { }
}
class Cat : Animal
{
public override void Play<T>(List<T> animals)
{
}
}
Run Code Online (Sandbox Code Playgroud)
最后,如果您使用的是C#4并且只需要对列表进行枚举而不进行修改,请查看Eric Lippert的答案IEnumerable<Animal>.
Jus*_*ner 12
您正在寻找通用收集协方差.但显然,您正在使用的C#版本不支持该功能.
您可以使用Cast<T>()扩展方法解决它.但请注意,这将创建原始列表的副本,而不是将原始列表作为其他类型传递:
cat.Play((new List<Cat>()).Cast<Animal>().ToList());
Run Code Online (Sandbox Code Playgroud)