【发布时间】:2021-08-27 07:17:18
【问题描述】:
我有以下无法编译的代码
using System.Collections.Generic;
public interface IElement
{
}
public class AElement : IElement
{
public void DoSomethingSpecial()
{ }
}
public class Container<TElement>
{
public List<TElement> Elements { get; } = new();
}
public class Program
{
public static Container<IElement> GetContainer()
{
var concreteContainer = new Container<AElement>();
concreteContainer.Elements.ForEach(e => e.DoSomethingSpecial());
return concreteContainer; // Cannot implicitly convert type 'Container<AElement>' to 'Container<IElement>'
}
public static void Main()
{
var myContainer = GetContainer();
}
}
我阅读了有关协方差、不变性、逆变性和输出类型的文档。 而且我比一开始更困惑。
有什么办法解决这个问题?
【问题讨论】:
-
AElement"is-a"IElement。但这不会使Container<AElement>"is-a"Container<IElement>。他们没有这样的关系。 -
对于为什么会发生这种情况,请参阅this。一旦你理解了这一点,你可能需要重新考虑你想做什么。
-
@Sweeper:回答“不要这样”也可以。但是,有人想要一个接口但在内部你必须使用具体类型(首先),这不是很常见吗?因为每个具体的实现都需要自定义行为?
-
@Klamsi 这并不矛盾。如果你有一个列表,比如说
List<IElement>,其中IElement有MethodA(),你可以将任何具体的类添加到实现该接口的列表中。其中任何一个都可以有自己的MethodA()实现。所以,调用foreach( var item in list ) item.MethodA();会执行相应的实现。 -
我会向后倾斜并重新考虑我的概念。