C# 实现嵌套的通用接口
我有以下类/接口:C# 实现嵌套的通用接口,c#,generics,interface,nested,nested-generics,C#,Generics,Interface,Nested,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 { } //模型 公共A类:IA{} //模型逻辑 公共类B:IB{} //模型接口 公共接口IA
// 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 { }
//模型
公共A类:IA{}
//模型逻辑
公共类B:IB{}
//模型接口
公共接口IA{}
//模型逻辑接口
公共接口IB,其中T:IA{}
我尝试使用以下代码创建一个新实例:
IB<IA> foo = new B();
IB foo=new B();
我得到以下错误:
Cannot implicitly convert type 'B' to 'IB<IA>'. An explicit conversion exists (are you missing a cast?)
无法将类型“B”隐式转换为“IB”。存在显式转换(是否缺少强制转换?)
有人能解释一下为什么这不可能吗?好的,让我们用
Fish
替换A
,IA
替换为IAnimal
,B
替换为水族馆
,而IB
替换为IContainer
。我们将向IContainer
添加一个成员,并为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!
请注意IB
上的协方差注释。此out
表示T
只能用作输出,不能用作输入。如果T
只是一个输出,那么某人就没有办法把老虎放进鱼缸,因为没有“放入”属性或方法
在我们向C#添加该功能时,我写了很多博客文章;如果您对该功能中的设计注意事项感兴趣,请参阅:
要修复代码,只需更改
public interface IB<T> where T : IA { }
公共接口IB,其中T:IA{}
到
公共接口IB,其中T:IA{}
当界面为空时,不容易看到。考虑在接口IB中有一个方法M:
public interface IB<T> where T : IA
{
void M(T t);
}
因此,如果您的代码可行,那么您可以调用:
IB<IA> foo = new B();
foo.M(new C());
IB foo=new B();
foo.M(新C());
问题是B类只接受A类型的对象。错误 你使用的是什么版本的C#?Eric LippertB是IB,而不是IB。变量无效:类型参数“T”在“xx.IContainer.Contents”上必须始终有效T是协变的。我得到了这个错误。我对协变的东西不熟悉。这个错误是什么意思?@Sandeep:你说你只会在输出位置使用T,但你在某种程度上是在输入位置使用T。
Contents
是带有setter的属性吗?如果很明显,T被用于输入位置,因此接口不能在T中协变。在所有与方差相关的问题中,这是迄今为止最有意义的最佳答案+1.
public interface IB<T> where T : IA
{
void M(T t);
}
public class B : IB<A>
{
public void M(A t)
{
// only object of type A accepted
}
}
public class C : IA { }
IB<IA> foo = new B();
foo.M(new C());