说我有像
这样的设置public interface IMyInterface { }
public class MyImplementation : IMyInterface { }
public class MyClass<T> where T : IMyInterface { }
我发现我不能做像
这样的替换var list = new List<MyClass<IMyInterface>>()
{
new MyClass<MyImplementation>()
}
因为我会收到错误
无法从
MyClass<MyImplementation>
转换为MyClass<IMyInterface>
这是否意味着我要做的是代码味?
答案 0 :(得分:0)
不允许这样做,因为T
中的List<T>
是不变的。这是一个可以解释的例子:
public interface IFruit
{
string Name { get; set; }
}
public class Apple : IFruit
{
public string Name { get; set; }
public string Color { get; set; }
}
public class Orange : IFruit
{
public string Name { get; set; }
}
让我们在列表中添加一些成果:
var fruits = new List<IFruit>();
fruits.Add(new Apple());
fruits.Add(new Orange());
稍后在代码中,你不知道添加了什么,你这样做:
Orange orange = fruits[0];
现在这不会编译,但它也没有意义,因为每个IFruit
都不是Apple
或Orange
。
如果编译器允许怎么办?
例如,如果让我们说,编译器允许您尝试的内容,如下所示:
// does not compile but let's say it did
List<Apple> fruits = new List<IFruit>();
然后,如果编译器允许,那么它也应该允许这个,因为它们都实现了IFruit
:
fruits.Add(new Apple());
fruits.Add(new Orange());
然后在代码中的某个地方执行此操作(因为它是一个苹果列表):
foreach (var thisFruit in fruits)
{
Console.WriteLine(thisFruit.Color)
}
崩溃!! 编译器在开始时没有阻止你,此时你正在查看代码并且它显示List<Apple>
,并且你编写了代码并编译了所有代码。在运行时, oh crap ,没有Color
属性,因为它是Orange
。
这就是不允许的原因。