我有以下类/接口(interface):
// Model
public class A : IA { }
// ModelLogic
public class B : IB<A> { }
// Model Interface
public interface IA { }
// ModelLogic Interface
public interface IB<T> where T : IA { }
我尝试使用以下代码创建一个新实例:
IB<IA> foo = new B();
我收到以下错误:
Cannot implicitly convert type 'B' to 'IB<IA>'. An explicit conversion exists (are you missing a cast?)
有人可以解释为什么这是不可能的吗?
最佳答案
好的,让我们替换A
与 Fish
, IA
与 IAnimal
, B
与 Aquarium
, 和 IB<T>
与 IContainer<T>
.我们将向 IContainer<T>
添加一个成员,以及 IAnimal
的第二次实现:
// Model
public class Fish : IAnimal { }
public class Tiger : IAnimal { }
// ModelLogic
public class Aquarium : IContainer<Fish>
{
public Fish Contents { get; set; }
}
// Model Interface
public interface IAnimal { }
// ModelLogic Interface
public interface IContainer<T> where T : IAnimal
{
T Contents { get; set; }
}
IContainer<IAnimal> foo = new Aquarium(); // Why is this illegal?
foo.Contents = new Tiger(); // Because this is legal!
您可以将老虎放入 foo -- foo 被定义为可以包含任何动物的容器。但是您只能将鱼放入水族箱。由于您可以合法地对 Aquarium
执行操作与您可以在 IContainer<IAnimal>
上执行的操作不同 , 类型不兼容。
您想要的功能称为通用接口(interface)协变,C# 4 支持它,但您必须向编译器证明您永远不会把老虎放进去你的鱼缸你想要做的是:
// Model
public class A : IA { }
// ModelLogic
public class B : IB<A> { }
// Model Interface
public interface IA { }
// ModelLogic Interface
public interface IB<out T> where T : IA { }
注意 IB
上的协方差注释.这out
表示 T
只能作为输出,不能作为输入。如果T
只是一个输出,那么就没有办法将老虎放入那个鱼缸,因为没有可能的“放入”属性或方法。
在我们将该功能添加到 C# 时,我写了很多博客文章;如果您对该功能的设计注意事项感兴趣,请参阅:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
关于c# - 实现嵌套的通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10352587/