如何在C#中的数组部分实现IList< T>? [英] How do arrays in C# partially implement IList<T>?

查看:227
本文介绍了如何在C#中的数组部分实现IList< T>?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此​​,大家可能都知道,在C#中的数组实施的IList< T> ,其他接口之间。不知怎的,虽然,他们这样做没有公开实施的IList&LT的Count属性; T> !数组只有一个长度属性。

So as you may know, arrays in C# implement IList<T>, among other interfaces. Somehow though, they do this without publicly implementing the Count property of IList<T>! Arrays have only a Length property.

这是C#的一个明显的例子/。NET打破自己的规则对接口的实现还是我失去了一些东西?

Is this a blatant example of C#/.NET breaking its own rules about the interface implementation or am I missing something?

推荐答案

在汉斯的回答光新的答案

由于汉斯给出的答案,我们可以看到执行是有些比我们想象的要复杂得多。无论是编译器和CLR尝试的很辛苦的给IM pression一个数组类型实现的IList&LT; T&GT; - 但阵列方差使这个棘手。相反,从汉斯答案,数组类型(单维的,从零开始的反正)不直接实现泛型集合,因为任何特定阵列类型的不是的System.Array - 这仅仅是基础的阵列的类型。如果你问一个数组类型是什么接口支持,它包含了一般类型:

Thanks to the answer given by Hans, we can see the implementation is somewhat more complicated than we might think. Both the compiler and the CLR try very hard to give the impression that an array type implements IList<T> - but array variance makes this trickier. Contrary to the answer from Hans, the array types (single-dimensional, zero-based anyway) do implement the generic collections directly, because the type of any specific array isn't System.Array - that's just the base type of the array. If you ask an array type what interfaces it supports, it includes the generic types:

foreach (var type in typeof(int[]).GetInterfaces())
{
    Console.WriteLine(type);
}

输出:

System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]

有关一维,从零开始的数组,至于的语言的来讲,该阵列确实落实的IList&LT; T&GT; 太。在C#规范的第12.1.2是这么说的。所以,无论底层实现的确,语言具有的的行为的仿佛 T [] 工具类型的IList&LT; T&GT ; 与任何其他接口。从这个角度来说,接口的的一些成员正在明确地执行落实(如计数)。这是在最好的解释的语言的是什么回事水平。

For single-dimensional, zero-based arrays, as far as the language is concerned, the array really does implement IList<T> too. Section 12.1.2 of the C# specification says so. So whatever the underlying implementation does, the language has to behave as if the type of T[] implements IList<T> as with any other interface. From this perspective, the interface is implemented with some of the members being explicitly implemented (such as Count). That's the best explanation at the language level for what's going on.

请注意,这只是保持着一维数组(和从零开始的数组,而不是C#作为语言说,大约非从零开始的数组东西)。 T [,] 的实施的IList&LT; T&GT;

Note that this only holds for single-dimensional arrays (and zero-based arrays, not that C# as a language says anything about non-zero-based arrays). T[,] doesn't implement IList<T>.

从CLR的角度来看,一些funkier是怎么回事。你不能为通用接口类型的接口映射。例如:

From a CLR perspective, something funkier is going on. You can't get the interface mapping for the generic interface types. For example:

typeof(int[]).GetInterfaceMap(typeof(ICollection<int>))

给出一个例外:

Gives an exception of:

Unhandled Exception: System.ArgumentException: Interface maps for generic
interfaces on arrays cannot be retrived.

那么,为什么古怪?好吧,我相信这是真的,由于阵列协方差,这是在类型系统疣,海事组织。尽管的IList&LT; T&GT; 没有的协变(也不可能是安全的),阵列协方差让这个工作:

So why the weirdness? Well, I believe it's really due to array covariance, which is a wart in the type system, IMO. Even though IList<T> is not covariant (and can't be safely), array covariance allows this to work:

string[] strings = { "a", "b", "c" };
IList<object> objects = strings;

...这使得它的的如 typeof运算(字符串[])工具的IList&LT;对象&gt; ,当它不是真的。

... which makes it look like typeof(string[]) implements IList<object>, when it doesn't really.

在CLI规范(ECMA-335)分区1,第8.7.1,有这样的:

The CLI spec (ECMA-335) partition 1, section 8.7.1, has this:

一个签名类型T是兼容-带有签名U型当且仅当下列中的至少一个保持

A signature type T is compatible-with a signature type U if and only if at least one of the following holds

...

T是一个从零开始的秩1阵列 V [] U 的IList&LT; W&GT; ,V是数组元素的兼容,用W

T is a zero-based rank-1 array V[], and U is IList<W>, and V is array-element-compatible-with W.

(它实际上并没有提及的ICollection&LT; W&GT; 的IEnumerable&LT; W&GT; 我相信这是一个错误的规范。)

(It doesn't actually mention ICollection<W> or IEnumerable<W> which I believe is a bug in the spec.)

对于非差异,CLI的规范伴随着直接的语言规范。从分区1第8.9.1:

For non-variance, the CLI spec goes along with the language spec directly. From section 8.9.1 of partition 1:

此外,与元素类型​​T创建的载体,实现接口 System.Collections.Generic.IList&LT; U&GT; ,其中U:= T(§8.7)

Additionally, a created vector with element type T, implements the interface System.Collections.Generic.IList<U>, where U := T. (§8.7)

(A 向量的是一个零基础的单维数组。)

(A vector is a single-dimensional array with a zero base.)

现在在的实施细则的,明确的CLR是做一些时髦的映射,以保持分配兼容性这里的术语:当的String [] 被要求为的ICollection&LT的执行情况;对象&gt; .Count之间,它不能处理,在的非常的正常方式。这是否算作显式接口实现?我认为这是合理的对待这样的说法,因为除非你直接问接口映射,它总的表现得的那样,从语言的角度来看。

Now in terms of the implementation details, clearly the CLR is doing some funky mapping to keep the assignment compatibility here: when a string[] is asked for the implementation of ICollection<object>.Count, it can't handle that in quite the normal way. Does this count as explicit interface implementation? I think it's reasonable to treat it that way, as unless you ask for the interface mapping directly, it always behaves that way from a language perspective.

什么 ICollection.Count

What about ICollection.Count?

到目前为止,我已经谈到了通用接口,但再有就是非泛型的ICollection 及其计数财产。这一次,我们的可以的获取接口的映射,而事实上,接口由的 的System.Array 。本文档中的 ICollection.Count 阵列属性实现指出,它与显式接口实现来实现。

So far I've talked about the generic interfaces, but then there's the non-generic ICollection with its Count property. This time we can get the interface mapping, and in fact the interface is implemented directly by System.Array. The documentation for the ICollection.Count property implementation in Array states that it's implemented with explicit interface implementation.

如果任何人都可以想办法在这种显式接口实现从正常显式接口实现不同的,我很乐意考虑进一步。

If anyone can think of a way in which this kind of explicit interface implementation is different from "normal" explicit interface implementation, I'd be happy to look into it further.

周围显式接口实现旧的答案

尽管如此,这是因为阵列的知识更复杂,你仍然可以做一些具有相同的可见的通过的explicit接口实现

Despite the above, which is more complicated because of the knowledge of arrays, you can still do something with the same visible effects through explicit interface implementation.

下面是一个简单的独立的例子:

Here's a simple standalone example:

public interface IFoo
{
    void M1();
    void M2();
}

public class Foo : IFoo
{
    // Explicit interface implementation
    void IFoo.M1() {}

    // Implicit interface implementation
    public void M2() {}
}

class Test    
{
    static void Main()
    {
        Foo foo = new Foo();

        foo.M1(); // Compile-time failure
        foo.M2(); // Fine

        IFoo ifoo = foo;
        ifoo.M1(); // Fine
        ifoo.M2(); // Fine
    }
}

这篇关于如何在C#中的数组部分实现IList&LT; T&GT;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆