根据CSharp语言规范.
接口定义了可以通过类和结构实现的契约.接口不提供它定义的成员的实现 - 它仅指定必须由实现接口的类或结构提供的成员.
所以我有这个:
interface ITest
{
IEnumerable<int> Integers { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的意思是."我与一个属性的合同是一个你可以枚举的整数集合".
然后我想要以下接口实现:
class Test : ITest
{
public List<int> Integers { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我得到以下编译器错误:
'Test'没有实现接口成员'ITest.Integers'.'Test.Integers'无法实现'ITest.Integers',因为它没有匹配的返回类型'System.Collections.Generic.IEnumerable'.
只要我可以说我的Test类实现了ITest契约,因为int属性的List实际上是int的IEnumerable.
那么c#编译器告诉我错误的方式呢?
Eri*_*ert 19
仅供参考,您想要的功能称为"虚方法返回类型协方差",正如您所发现的那样,C#不支持它.它是其他面向对象语言的一个特性,比如C++.
虽然我们经常收到此功能的请求,但我们没有计划将其添加到该语言中.这不是一个可怕的特征; 如果我们拥有它,我会使用它.但是我们有很多理由不这样做,包括CLR不支持它,它为可版本化的组件添加了新的和有趣的故障模式,Anders认为它不是一个非常有趣的功能,而且我们有很多很多更高的优先级和有限的预算.
顺便说一下,尽管人们一直要求我们使用虚方法返回类型协方差,但是没有人要求虚方法形式参数类型相反,即使逻辑上它们本质上是相同的特征.也就是说,我有一个带有长颈鹿的虚拟方法/接口方法M,我想用一个带动物的方法M来覆盖/实现它.
你不能这样做,因为你手上有一个重大问题,具体取决于实施情况,如果这是允许的话.考虑:
interface ITest
{
IEnumerable<int> Integers { get; set; }
}
class Test : ITest
{
// if this were allowed....
public List<int> Integers { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这将允许:
ITest test = new Test();
test.Integers = new HashSet<int>();
Run Code Online (Sandbox Code Playgroud)
这会使Test的合同无效,因为Test说它包含List<int>.
现在,您可以使用显式接口实现来允许它满足两个签名,具体取决于它是从ITest引用还是Test引用调用:
class Test : ITest
{
// satisfies interface explicitly when called from ITest reference
IEnumerable<int> ITest.Integers
{
get
{
return this.Integers;
}
set
{
this.Integers = new List<int>(value);
}
}
// allows you to go directly to List<int> when used from reference of type Test
public List<int> Integers { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
简单的事实是,如果界面说:
IInterface{
Animal A { get; }
}
Run Code Online (Sandbox Code Playgroud)
然后该属性的实现必须与该类型完全匹配.试图将其实现为
MyClass : IInterface{
Duck A { get; }
}
Run Code Online (Sandbox Code Playgroud)
不起作用 - 即使Duck是一个Animal
相反,你可以这样做:
MyClass : IInterface{
Duck A { get; }
Animal IInterface.A { get { return A; } }
}
Run Code Online (Sandbox Code Playgroud)
即提供IInterface.A成员的显式实现,利用Duck和之间的类型关系Animal.
在你的情况下,这意味着至少实现,吸气剂,ITest.Integers为
IEnumerable<int> ITest.Integers { get { return Integers; } }
Run Code Online (Sandbox Code Playgroud)
要实现setter,您需要乐观地投射或在输入值上使用.ToList().
请注意,这些显式实现的使用A和Integers内部不是递归的,因为显式接口实现在类型的公共视图中是隐藏的 - 它们仅在调用者通过它的IInterface/ ITest接口实现与类型进行通信时启动.