实现嵌套通用接口

我有以下类/接口:

// Model public class A : IA { } // ModelLogic public class B : IB { } // Model Interface public interface IA { } // ModelLogic Interface public interface IB where T : IA { } 

我尝试使用以下代码创建一个新实例:

 IB foo = new B(); 

我收到以下错误:

 Cannot implicitly convert type 'B' to 'IB'. An explicit conversion exists (are you missing a cast?) 

有人可以解释为什么这是不可能的?

好吧,让我们用Fish取代A ,用IAnimal代替IA ,用Aquarium IAnimal B ,用IContainer代替IB IContainer 。 我们将向IContainer添加一个成员,并向IAnimal添加第二个实现:

 // Model public class Fish : IAnimal { } public class Tiger : IAnimal { } // ModelLogic public class Aquarium : IContainer { public Fish Contents { get; set; } } // Model Interface public interface IAnimal { } // ModelLogic Interface public interface IContainer where T : IAnimal { T Contents { get; set; } } IContainer foo = new Aquarium(); // Why is this illegal? foo.Contents = new Tiger(); // Because this is legal! 

你可以将老虎放入foo – foo被输入为可容纳任何动物的容器 。 但是你只能将鱼放入水族馆。 由于您可以在Aquarium上合法执行的操作与您在IContainer上执行的操作不同 ,因此类型不兼容。

您想要的function称为通用接口协方差 ,它受C#4支持,但您必须向编译器certificate您永远不会将老虎放入您的鱼缸。 你想要做的是:

 // Model public class A : IA { } // ModelLogic public class B : IB { } // Model Interface public interface IA { } // ModelLogic Interface public interface IB where T : IA { } 

请注意IB上的协方差注释。 这意味着T只能用作输出 ,而不能用作输入。 如果T只是一个输出,那么就没有人可以将老虎放入该鱼缸,因为没有“投入”财产或方法。

我在将这个function添加到C#时写了一些博客文章; 如果您对该function的设计注意事项感兴趣,请参阅:

http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/

要修复代码,只需更改即可

 public interface IB where T : IA { } 

 public interface IB where T : IA { } 

当你有空接口时,不容易看到。 考虑在接口IB中有一个方法M:

 public interface IB where T : IA { void M(T t); } 

这是B的实现:

 public class B : IB { public void M(A t) { // only object of type A accepted } } 

然后你有对象C,它也实现了IA:

 public class C : IA { } 

所以,如果您的代码可以,那么您可以调用:

 IB foo = new B(); foo.M(new C()); 

问题是B类只接受A类对象。错误!