实现嵌套的通用接口(Implementing nested generic Interfaces)

2019-06-24 00:39发布

我有以下类/接口:

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

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

Answer 1:

行,让我们取代AFishIAIAnimalBAquarium ,和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!

你可以把虎成富- 富的类型是可以包含任何动物的容器 。 但是,你只能放鱼入水族馆。 既然你可以在一个法律上执行的操作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 { }

注意协方差注释IB 。 这个out意味着T只能用作输出 ,而不是作为一个输入。 如果T只有一个输出,那么有没有办法的人把老虎成鱼缸,因为没有“投入”属性或方法成为可能。

我写了一些,同时我们添加这个功能到C#博客文章; 如果你有兴趣在设计中考虑,进入该功能,请参阅:

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



Answer 2:

要解决你的代码,只是改变

public interface IB<T> where T : IA { }

public interface IB<out T> where T : IA { }


Answer 3:

这是不容易看到当你有空接口。 考虑一下你在界面IB一个方法M.:

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

这里是实现B的:

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

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

public class C : IA { } 

所以,如果你的代码将是可能的,那么你可以拨打:

IB<IA> foo = new B();
foo.M(new C());

问题是,B类只接受A型错误的对象!



文章来源: Implementing nested generic Interfaces