为什么在实现接口时我不能使用兼容的具体类型

我希望能够做到这样的事情:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test { public interface IFoo { IEnumerable integers { get; set; } } public class Bar : IFoo { public List integers { get; set; } } } 

为什么编译器抱怨..?

 Error 2 'Test.Bar' does not implement interface member 'Test.IFoo.integers'. 'Test.Bar.integers' cannot implement 'Test.IFoo.integers' because it does not have the matching return type of 'System.Collections.Generic.IEnumerable'. 

我理解接口说IEnumerable,类使用List,但List IEnumerable …..

我能做什么? 我不想在类中指定IEnumerable,我想使用一个实现IEnumerable的具体类型,比如List …

这是类型协方差/逆变问题(参见http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#C.23 )。

有一种解决方法:使用显式接口,如下所示:

 public class Bar : IFoo { private IList _integers; IEnumerable IFoo.integers { get { return _integers }; set { _integers = value as IList; } } public IList integers { get { return _integers; } set { _integers = vale; } } } 

请注意, integers应该是TitleCased以符合.NET的指导原则。

希望您能在上面的代码中看到问题: IList IEnumerable仅与访问者兼容IEnumerable ,但不适用于设置。 如果有人调用IFoo.integers = new Qux() (其中Qux : IEnumerable不是 Qux : IList )会发生什么。

虽然List实现IEnumerable,但这不是接口的工作方式。 接口确切地指定了需要为属性公开哪些类型。 如果你创建了一个通用的界面

 public interface IFoo where T : IEnumerable { T integers { get; set; } } 

然后,您可以使用IFoo>以您期望的方式实现它。

除非你在幕后进行,否则你无法使用具体的类型。 问题是你可以获取和设置属性。

您的接口指定该属性的类型为IEnumerableHashSet实现IEnumerable 。 这意味着以下应该可以正常工作:

 IFoo instance = new Bar(); instance.integers = new HashSet(); 

但是,由于您尝试使用具体类型List实现接口,因此分配无法工作。

假设您不经常需要重新分配集合,最简单的修复方法是仅为集合指定getter:

 public interface IFoo { IEnumerable Integers { get; } } public class Bar { public List Integers { get; private set; } public Bar(List list) { Integers = list; } }