12

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test
{
    public interface IFoo
    {
        IEnumerable<int> integers { get; set; }
    }

    public class Bar : IFoo
    {
        public List<int> 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<int>'.

我知道接口说 IEnumerable 并且该类使用 List,但是 ListIEnumerable .....

我能做些什么?我不想在类中指定 IEnumerable,我想使用实现 IEnumerable 的具体类型,例如 List...

4

3 回答 3

12

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

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

public class Bar : IFoo {

    private IList<int> _integers;

    IEnumerable<int> IFoo.integers {
        get { return _integers };
        set { _integers = value as IList<int>; }
    }

    public IList<int> integers {
        get { return _integers; }
        set { _integers = vale; }
    }
}

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

希望你能在上面的代码中看到问题:只对访问器IList<int>兼容,对设置不兼容。IEnumerable<int>如果有人打电话IFoo.integers = new Qux<int>()(whereQux : IEnumerable<int>不是 Qux : IList<int>)会发生什么。

于 2013-03-19T02:45:24.193 回答
5

尽管 List 实现了 IEnumerable ,但这不是接口的工作方式。该接口准确地指定了哪些类型需要为属性公开。如果您创建了一个通用接口,例如

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

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

于 2013-03-19T02:46:37.297 回答
3

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

您的界面指定该属性的类型为IEnumerable<int>HashSet<int>实现IEnumerable<int>。这意味着以下应该可以正常工作:

IFoo instance = new Bar();
instance.integers = new HashSet<int>();

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

假设您不需要经常重新分配集合,最简单的解决方法是只为集合指定一个 getter:

public interface IFoo
{
    IEnumerable<int> Integers { get; }
}

public class Bar
{
    public List<int> Integers { get; private set; }

    public Bar(List<int> list)
    {
        Integers = list;
    }
}
于 2013-03-19T02:47:28.080 回答