关于C#编程指南中数组实现IEnumerable<T>的正确性疑问及多维数组LINQ方法调用问题
IEnumerable<T>的疑问解答 这是个非常容易踩坑的细节问题,其实C#编程指南的描述并没有错误,只是我们需要理清多维数组在接口实现上的特殊之处:
核心原因:多维数组未直接实现泛型IEnumerable<T>
所有数组确实都继承自抽象基类Array,而Array也确实实现了非泛型的IEnumerable接口。但泛型版本的IEnumerable<T>,只有一维数组是直接实现的——多维数组(比如你用到的int[,,,]这类矩形数组)并没有实现对应的IEnumerable<T>接口,这就是关键差异。
为什么直接用Any()会报错?
LINQ的Any扩展方法是定义在IEnumerable<T>接口上的,由于多维数组本身没有实现这个泛型接口,编译器找不到匹配的扩展方法,于是就抛出了CS1061错误。
为什么Cast<int>()能解决问题?
Cast<T>是针对**非泛型IEnumerable**的扩展方法,它会遍历非泛型枚举中的每个元素,并将其强制转换为T类型,最终返回一个IEnumerable<T>对象。这样一来,我们就得到了符合LINQ泛型方法要求的集合,自然就能调用Any()了。
为什么直接强制转IEnumerable<int>不行?
刚才已经提到,多维数组根本没有实现IEnumerable<int>这个泛型接口,所以这种强制转换是不合法的,编译器抛出CS0030错误完全合理。如果要通过强制转换的方式处理,应该先转成非泛型的IEnumerable,再进行类型转换:
bool result2 = ((IEnumerable)array4).Cast<int>().Any(x => x == 1);
这样写法是可以正常运行的。
额外补充:一维数组的特殊性
一维数组(比如int[])是直接实现了IEnumerable<T>的,所以你直接对一维数组调用Any()、Where()等LINQ泛型方法都不会有问题——这也是为什么有时候我们会误以为所有数组都支持这些操作的原因。
内容的提问来源于stack exchange,提问作者Olivier Jacot-Descombes

