Joa*_*nge 22 .net c# linq arrays ienumerable
我有一些像这样的代码:
public class EffectValues : IEnumerable<object>
{
public object [ ] Values { get; set; }
public IEnumerator<object> GetEnumerator ( )
{
return this.Values.GetEnumerator ( );
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ( )
{
return this.GetEnumerator ( );
}
}
Run Code Online (Sandbox Code Playgroud)
但编译器抱怨说:
"无法将类型'System.Collections.IEnumerator'隐式转换为'System.Collections.Generic.IEnumerator'.存在显式转换(您是否错过了转换?)"
我以为Array类型实现了IEnumerable接口,不是吗?因为我可以直接在Values实例上使用Linq功能.
Eri*_*ert 41
这是一个微妙而有点不幸的事.简单的解决方法是:
public IEnumerator<object> GetEnumerator ( )
{
return ((IEnumerable<object>)this.Values).GetEnumerator ( );
}
Run Code Online (Sandbox Code Playgroud)
我以为Array类型实现了IEnumerable接口,不是吗?
规则是:
IList<T>
,IEnumerable<T>
等等.IEnumerable<T>
请注意,第三点不是
IList<T>
,IEnumerable<T>
依此类推,在T []上定义的公共方法和属性隐式实现成员你去吧 当你查找GetEnumerator时,我们在object []上查找并找不到它,因为object [] IEnumerable<object>
显式实现.它可以转换为IEnumerable<object>
,并且可转换性不计入查找.(你不会期望在int上出现"double"方法只是因为int可以转换为double.)然后我们查看基类型,发现System.Array使用公共方法实现IEnumerable,所以我们已经找到了我们的GetEnumerator.
也就是说,想想这样:
namespace System
{
abstract class Array : IEnumerable
{
public IEnumerator GetEnumerator() { ... }
...
}
}
class object[] : System.Array, IList<object>, IEnumerable<object>
{
IEnumerator<object> IEnumerable<object>.GetEnumerator() { ... }
int IList<object>.Count { get { ... } }
...
}
Run Code Online (Sandbox Code Playgroud)
当你在object []上调用GetEnumerator时,我们看不到实现是一个显式的接口实现,所以我们去基类,它有一个可见的.
如何"动态"生成所有object [],int [],string [],SomeType []类?
魔法!
这不是泛型,对吧?
对.数组是非常特殊的类型,它们在深入的CLR类型系统中被烘焙.虽然它们在许多方面与泛型非常相似.
看起来这
class object [] : System.Array
是用户无法实现的,对吧?
对,这只是为了说明如何思考它.
你觉得哪一个更好:
GetEnumerator()
投入IEnumerable<object>
,或只是使用foreach
和yield
?
问题是形象不对称.您没有将GetEnumerator强制转换为IEnumerable<object>
.您可以将数组转换为IEnumerable<object>
或者将GetEnumerator转换为IEnumerator<object>
.
我可能会将值转换为IEnumerable<object>
并调用GetEnumerator
它.
我可能会使用强制转换,但我想知道这是否是你或一些程序员可以阅读代码的地方,会认为它不太清楚.
我认为演员阵容非常清楚.
当你说隐式实现时,你的意思是以Interface.Method的形式,对吧?
不,相反:
interface IFoo { void One(); void Two(); }
class C : IFoo
{
public void One() {} // implicitly implements IFoo.One
void IFoo.Two() {} // explicitly implements IFoo.Two
}
Run Code Online (Sandbox Code Playgroud)
第一个声明默默地实现该方法.第二个是明确它实现的接口方法.
这样实现的原因是什么
IEnumerable<T>
,而不是公共方法的隐式实现?我很好奇因为你说"这是一个微妙而有点不幸",所以看起来这是因为一个较老的决定迫使你这样做我想象?
我不知道是谁做出了这个决定.不过有点不幸.它至少让一个用户感到困惑 - 你 - 它也让我困惑了几分钟!
我原以为Array类型会是这样的:
public class Array<T> : IEnumerable<T>
等等.但是有一些神奇的代码呢,对吧?
对.正如你在昨天的问题中所指出的那样,如果我们在CLR v1中使用泛型,事情会有很大的不同.
数组本质上是一种通用的集合类型.因为它们是在没有泛型的类型系统中创建的,所以类型系统中必须有许多特殊代码来处理它们.
下次设计类型系统时,将泛型置于v1中,并确保获得强大的集合类型,从一开始就将可空类型和非可空类型烘焙到框架中.事后添加泛型和可空值类型很困难.
归档时间: |
|
查看次数: |
5117 次 |
最近记录: |