Bry*_*ter 14 c# generics nested interface nested-generics
我有以下类/接口:
// 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 { }
Run Code Online (Sandbox Code Playgroud)
我尝试使用以下代码创建一个新实例:
IB<IA> foo = new B();
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
Cannot implicitly convert type 'B' to 'IB<IA>'. An explicit conversion exists (are you missing a cast?)
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么这是不可能的?
Eri*_*ert 43
好吧,让我们更换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!
Run Code Online (Sandbox Code Playgroud)
你可以将一只老虎放入foo - foo被输入为可以包含任何动物的容器.但你只能把鱼放入水族馆.既然你可以在一个法律上执行的操作Aquarium
是不同的比你可以上执行的操作IContainer<IAnimal>
,该类型不兼容.
你想要的功能被称为通用接口协方差,它是由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 { }
Run Code Online (Sandbox Code Playgroud)
注意协方差注释IB
.这out
意味着T
只能用作输出,而不能用作输入.如果T
只是一个输出,那么没有人可以将老虎放入该鱼缸,因为没有"投入"财产或方法.
我在将这个功能添加到C#时写了一些博客文章; 如果您对该功能的设计注意事项感兴趣,请参阅:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/