泛型参数不可分配
本文关键字:可分配 不可分 参数 泛型 | 更新日期: 2023-09-27 18:36:37
我正在使用C#.NET 3.5。我得到
参数类型"GenericTest.BarkStrategy"不能分配给参数类型"GenericsTest.IAnimalStrategy"
使用以下(对于此问题尽可能简化)代码:
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> { }
}
你必须告诉编译器你的接口是协变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 中可用:如何在 C# 4.0 中实现泛型协方差和逆方差?
为了理解问题,你可以忘记列表,这一行不编译:
IAnimalStrategy<IAnimal> s = new BarkStrategy();
IAnimalStrategy<IAnimal>
接口可以在 IAnimal 上执行操作,可以设置类型 IAnimal
interface IAnimalStrategy<T> where T : IAnimal
{
T Animal {get; set;}
}
然后你就可以做一些类似的事情
IAnimalStrategy<IAnimal> s = new BarkStrategy();
s.Animal = new Cat();
它会吹到你的脸上。所以 C#3.5 不允许你这样做.
C#4.0 将允许你这样做,如果你说 T 与 out
关键字是协变
interface IAnimalStrategy<out T> where T : IAnimal
{
T Animal {get; set;}
}
这会再次吹,
无效方差:类型参数"T"必须始终有效动物战略"。"T"是协变。
协方差和逆变很难理解,我建议你阅读 Eric Lippert 博客上的精彩系列:C# 中的协方差和逆变