如您所知,C#中的数组实现IList 以及其他接口。尽管不知何故,他们在没有公开实现Count属性的情况下执行此操作IList 。数组只有一个Length属性。
这是C#/。NET违反其关于接口实现的规则的公然示例还是我错过了一些东西?
如您所知,C#中的array实现IList ,以及其他接口
好吧,是的,不是,不是。这是.NET 4框架中Array类的声明:
[Serializable, ComVisible(true)] public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable { // etc.. } 它实现System.Collections.IList,而不是 System.Collections.Generic.IList <>。不能,数组不是通用的。通用IEnumerable <>和ICollection <>接口也是如此。
但是CLR可以动态创建具体的数组类型,因此可以从技术上创建实现这些接口的数组类型。但是事实并非如此。请尝试以下代码,例如:
using System; using System.Collections.Generic;
class Program { static void Main(string[] args) { var goodmap = typeof(Derived).GetInterfaceMap(typeof(IEnumerable )); var badmap = typeof(int[]).GetInterfaceMap(typeof(IEnumerable )); // Kaboom } } abstract class Base { } class Derived : Base, IEnumerable { public IEnumerator GetEnumerator() { return null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } 对于具有“找不到接口”的具体数组类型,GetInterfaceMap()调用失败。但是对IEnumerable <>的强制转换可以正常工作。
这是鸭子般的嘎嘎打字。正是这种类型的输入产生了一种错觉,即每个值类型都源自从Object派生的ValueType。就像值类型一样,编译器和CLR都具有数组类型的特殊知识。编译器会看到您尝试转换为IList <>的尝试,并说“好吧,我知道该怎么做!”。并发出castclass IL指令。CLR对此没有任何问题,它知道如何提供可用于基础数组对象的IList <>实现。它具有否则隐藏的System.SZArrayHelper类的内置知识,该类实际上是实现这些接口的包装。
您所询问的Count属性看起来并不像每个人都声称的那样明显地没有做到这一点:
internal int get_Count<T>() {
//! Warning: "this" is an array, not an SZArrayHelper. See comments above
//! or you may introduce a security hole!
T[] _this = JitHelpers.UnsafeCast<T[]>(this);
return _this.Length;
}
是的,您当然可以称该评论为“违反规则” :)否则,它很方便。而且隐藏得非常好,您可以在SSCLI20(CLR的共享源分发)中进行检查。搜索“ IList”以查看发生类型替换的位置。实际运行中最好的地方是clr / src / vm / array.cpp,GetActualImplementationForArrayGenericIListMethod()方法。
与CLR中允许为WinRT(又称为Metro)编写托管代码的语言投影中发生的情况相比,CLR中的这种替换相当温和。几乎所有核心.NET类型都在那里被替换。例如,IList <>映射到IVector <>,这是一个完全不受管的类型。COM本身是替代品,不支持泛型类型。
好吧,那是看幕后发生的事情。这可能是非常不舒服,陌生和陌生的海洋,并且地图的尽头有龙。使地球平坦并为托管代码中实际发生的事情制作不同的图像非常有用。这样就可以将其映射到每个人最喜欢的答案。对于值类型,这不太好用(不要变异一个结构!),但是这个隐藏得很好。GetInterfaceMap()方法失败是我能想到的唯一的泄漏。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。