c#接口实现 - 为什么这不构建?

时间:2011-11-23 17:57:47

标签: c# arrays interface ienumerable implementation

很抱歉,如果以前曾经问过这个问题,那么google几乎是不可能的。我认为int数组实现IEnumerable,因此Thing应该能够实现IThing。怎么没有?

public interface IThing
{
    IEnumerable<int> Collection { get; }
}

public class Thing : IThing
{
    public int[] Collection { get; set; }
}

请注意

public class Thing : IThing
{
    public int[] Array { get; set; }
    public IEnumerable<int> Collection
    {
         get
         {
              return this.Array;
         }
    }
}

很好。

7 个答案:

答案 0 :(得分:7)

对于要实现的接口,方法签名和返回类型必须相同,因此int []可转换为IEnumerable这一事实对我来说没什么区别。

答案 1 :(得分:6)

不同实现中属性的返回类型不同 - 返回int[]与返回IEnumerable<int>不同。

就实现界面而言 - 类型必须与完全匹配

这应该可以正常工作:

public class Thing : IThing
{
    public IEnumerable<int> Collection { get; set; }
}

答案 2 :(得分:6)

接口实现必须完全实现接口。这可以防止您返回实现该接口的类型作为成员。

如果您希望这样做,一个选项是明确实现接口

public interface IThing
{
    IEnumerable<int> Collection { get; }
}

public class Thing : IThing
{
    public int[] Collection { get; set; }
    IEnumerable<int> 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();
    }
}

答案 3 :(得分:3)

您的实现应该完全按照原样实现接口。

答案 4 :(得分:2)

因为签名

IEnumerable<int> Collection { get; }

的签名不同
int[] Collection { get; set; }

当您实现界面时,签名应该完全相同。

答案 5 :(得分:2)

这是协方差/逆变可以派上用场的地方。此功能允许您在泛型上定义输入/输出标记,并允许您执行以下操作:

public interface IThing<out T> where T : IEnumerable<int> {
    T Collection { get; }
}

public class Thing : IThing<int[]> {
    public int[] Collection { get; set; }
}

然后,这将允许您定义其他实现,然后仍然将它们一起用作IThing<IEnumerable<int>> s。

public class Thing2 : IThing<List<int>> {
    public List<int> Collection { get; set; }
}

class Program {
    static void Main() {
        var x = new Thing();
        var y = new Thing2();
        new List<IThing<IEnumerable<int>>> { x, y };
    }
}

这种方法优于显式接口实现的优点是你保证 IThing.Collection与Thing.Collection完全相同的方法,而在显式实现时,它们实际上是不同的方法所以没有这样的保证。缺点当然是你必须更加明确,因此它使代码看起来有点“吵闹”。

不确定为什么C#编译器无法隐含地解决这个问题;我的猜测是,用额外的支票编译只需要太长时间。

答案 6 :(得分:0)

如果您阅读Interfaces的定义,您会注意到它说“......该类的相应成员必须是公共的,非静态的,并且与接口成员具有相同的名称和签名。“

虽然数组或List实现了IEnumerable,但不是 IEnumerable对象。那是你的问题。

您的签名必须符合才能生效。您会注意到public List<int> Collection { get; set; }也不起作用。您将需要更改Interface的属性定义,或者让您的实现返回IEnumerable <int>,就像您的第二个工作示例一样。