Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现嵌套的通用接口_C#_Generics_Interface_Nested_Nested Generics - Fatal编程技术网

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());