c#接口实现 – 为什么这不构建?
很抱歉,如果之前有人询问过,但谷歌几乎不可能。 我认为int数组实现IEnumerable,因此Thing应该能够实现IThing。 怎么没有?
public interface IThing { IEnumerable Collection { get; } } public class Thing : IThing { public int[] Collection { get; set; } }
注意
public class Thing : IThing { public int[] Array { get; set; } public IEnumerable Collection { get { return this.Array; } } }
很好。
接口实现必须完全实现接口。 这可以防止您返回实现该接口的类型作为成员。
如果您希望这样做,一个选项是明确实现接口:
public interface IThing { IEnumerable Collection { get; } } public class Thing : IThing { public int[] Collection { get; set; } IEnumerable IThing.Collection { get { return this.Collection; } } }
这允许类的公共API使用具体类型,但接口实现要正确实现。
例如,有了上述内容,您可以编写:
internal class Test { private static void Main(string[] args) { IThing thing = new Thing { Collection = new[] { 3, 4, 5 } }; foreach (var i in thing.Collection) { Console.WriteLine(i); } Console.ReadKey(); } }
对于要实现的接口,方法签名和返回类型必须相同,因此int []可转换为IEnumerable这一事实对我来说没什么区别。
不同实现中属性的返回类型是不同的 – 返回int[]
与返回IEnumerable
。
就实现接口而言 – 类型必须完全匹配。
这应该工作得很好:
public class Thing : IThing { public IEnumerable Collection { get; set; } }
您的实现应该完全按照原样实现接口。
因为签名了
IEnumerable Collection { get; }
与签名不一样
int[] Collection { get; set; }
当您实现接口时,签名应该完全相同。
这就是协方差/逆变可以派上用场的地方。 此function允许您在generics上定义输入/输出标记,并允许您执行以下操作:
public interface IThing where T : IEnumerable { T Collection { get; } } public class Thing : IThing { public int[] Collection { get; set; } }
然后,这将允许您定义其他实现,然后仍然将它们一起用作IThing
s。
public class Thing2 : IThing> { public List Collection { get; set; } } class Program { static void Main() { var x = new Thing(); var y = new Thing2(); new List>> { x, y }; } }
这种方法优于显式接口实现的优点是,您可以保证 IThing.Collection与Thing.Collection完全相同,而在显式实现时,它们实际上是不同的方法,因此没有这样的保证。 缺点当然是你必须更加明确,因此它使代码看起来有点“吵闹”。
不知道为什么C#编译器无法隐含地解决这个问题; 我的猜测是,用额外的检查编译只需要太长时间。
如果您阅读了Interfaces的定义,您会注意到它表示“……该类的相应成员必须是公共的,非静态的,并且具有与接口成员相同的名称和签名。”
虽然数组或List实现IEnumerable,但它不是 IEnumerable对象。 那是你的问题。
您的签名必须匹配才能正常工作。 你会注意到public List
public List
public List
也行不通。 您将需要更改Interface的属性定义,或者让您的实现返回IEnumerable
就像您的第二个工作示例一样。