将实现替换为类型为T的参数化类的T.

时间:2018-05-16 21:32:27

标签: c# .net oop

说我有像

这样的设置
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>

这是否意味着我要做的是代码味?

1 个答案:

答案 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都不是AppleOrange

如果编译器允许怎么办?

例如,如果让我们说,编译器允许您尝试的内容,如下所示:

// 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

这就是不允许的原因。