我正在使用 C#.NET 3.5。我得到
使用以下(对于这个问题尽可能简化)代码:
using System.Collections.Generic;
namespace GenericsTest {
class Program {
static void Main(string[] args) {
List<IAnimalStrategy<IAnimal>> strategies =
new List<IAnimalStrategy<IAnimal>>();
strategies.Add(new BarkStrategy());
}
}
interface IAnimal { }
interface IAnimalStrategy<T> where T : IAnimal { }
class Dog : IAnimal { }
class BarkStrategy : IAnimalStrategy<Dog> { }
}
最佳答案
你必须告诉编译器你的接口(interface)是协变的:IAnimalStrategy<out T>
namespace GenericsTest
{
class Program
{
static void Main(string[] args)
{
List<IAnimalStrategy<IAnimal>> strategies = new List<IAnimalStrategy<IAnimal>>();
strategies.Add(new BarkStrategy());
}
}
interface IAnimal { }
interface IAnimalStrategy<out T> where T : IAnimal { }
class Dog : IAnimal { }
class BarkStrategy : IAnimalStrategy<Dog> { }
}
不幸的是,它仅在 C# 4.0 中可用:How is Generic Covariance & Contra-variance Implemented in C# 4.0?
为了理解这个问题,你可以忘记列表,这一行不会编译:
IAnimalStrategy<IAnimal> s = new BarkStrategy();
IAnimalStrategy<IAnimal>
接口(interface)可以在 IAnimal 上做一些事情,也许设置一个 IAnimal
类型的属性interface IAnimalStrategy<T> where T : IAnimal
{
T Animal {get; set;}
}
然后你就可以做类似的事情
IAnimalStrategy<IAnimal> s = new BarkStrategy();
s.Animal = new Cat();
它会吹在你的脸上。所以 C#3.5 不允许你这样做。
如果您说 T 与
out
关键字是协变的,C#4.0 将允许您这样做interface IAnimalStrategy<out T> where T : IAnimal
{
T Animal {get; set;}
}
这又要吹了
协变和逆变很难理解,我建议您阅读 Eric Lippert 博客上的精彩系列:Covariance and Contravariance in C#
关于c# - 通用参数不可分配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19541699/