IEnumerator的Current属性,是否在foreach时会自动类型转换?

tlzjff 2009-06-03 11:29:14
MSDN上抄了段代码学习,发现IEnumerator的Current属性是一个object类型,但是在foreach的时候却能自动根据in前面的类型去自动匹配,调试时候断点进入Current
属性,因为Current返回的是一个object而我foreach里遍历类型却是一个CLASS,Class=object应该会报错呀,难道foreach里面会帮你类型转换么?为了证明这一点,
我用ildasmc查看了IL的代码
虽然里面基本都看不懂,不过有一行
L_0079: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
猜测是在foreach时候调用的~
因为本人看不懂IL的代码,所以不知道IL里面哪里一行是类型转换,以证明foreach时会自动转换类型,
以下具体贴出.CS代码和IL代码,望高手指点我foreach迷津

C#代码

public class MyIEnumberableAndIEnumberatorTest
{
public void DemoStart()
{
Person[] pe = new Person[10];
for (int i = 0; i < pe.Length; i++)
{
pe[i] = new Person(i.ToString(), Convert.ToString(i * i));
}
People po = new People(pe);
string str="";

foreach (Person a in po)
{
str += a.firstName + a.lastName;
Person aa = a;
}
}


public class Person
{
public Person(string fName, string lName)
{
this.firstName = fName;
this.lastName = lName;
}

public string firstName;
public string lastName;
}


public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];

for (int i = 0; i < pArray.Length; i++)
{
_people[i] = pArray[i];
}
}

public IEnumerator GetEnumerator()
{
return new PeopleEnum(_people);
}
}

public class PeopleEnum : IEnumerator
{
public Person[] _people;

// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;

public PeopleEnum(Person[] list)
{
_people = list;
}

public bool MoveNext()
{
position++;
return (position < _people.Length);
}

public void Reset()
{
position = -1;
}

public object Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
}



.method public hidebysig instance void DemoStart() cil managed
{
// コード サイズ 165 (0xa5)
.maxstack 5
.locals init ([0] class ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person[] pe,
[1] int32 i,
[2] class ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/People po,
[3] string str,
[4] class ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person a,
[5] class ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person aa,
[6] bool CS$4$0000,
[7] class [mscorlib]System.Collections.IEnumerator CS$5$0001,
[8] class [mscorlib]System.IDisposable CS$0$0002)
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newarr ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person
IL_0008: stloc.0
IL_0009: ldc.i4.0
IL_000a: stloc.1
IL_000b: br.s IL_002a
IL_000d: nop
IL_000e: ldloc.0
IL_000f: ldloc.1
IL_0010: ldloca.s i
IL_0012: call instance string [mscorlib]System.Int32::ToString()
IL_0017: ldloc.1
IL_0018: ldloc.1
IL_0019: mul
IL_001a: call string [mscorlib]System.Convert::ToString(int32)
IL_001f: newobj instance void ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person::.ctor(string,
string)
IL_0024: stelem.ref
IL_0025: nop
IL_0026: ldloc.1
IL_0027: ldc.i4.1
IL_0028: add
IL_0029: stloc.1
IL_002a: ldloc.1
IL_002b: ldloc.0
IL_002c: ldlen
IL_002d: conv.i4
IL_002e: clt
IL_0030: stloc.s CS$4$0000
IL_0032: ldloc.s CS$4$0000
IL_0034: brtrue.s IL_000d
IL_0036: ldloc.0
IL_0037: newobj instance void ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/People::.ctor(class ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person[])
IL_003c: stloc.2
IL_003d: ldstr ""
IL_0042: stloc.3
IL_0043: nop
IL_0044: ldloc.2
IL_0045: callvirt instance class [mscorlib]System.Collections.IEnumerator ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/People::GetEnumerator()
IL_004a: stloc.s CS$5$0001
.try
{
IL_004c: br.s IL_0077
IL_004e: ldloc.s CS$5$0001
IL_0050: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
IL_0055: castclass ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person
IL_005a: stloc.s a
IL_005c: nop
IL_005d: ldloc.3
IL_005e: ldloc.s a
IL_0060: ldfld string ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person::firstName
IL_0065: ldloc.s a
IL_0067: ldfld string ConsoleApplication1.MyIEnumberableAndIEnumberatorTest/Person::lastName
IL_006c: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0071: stloc.3
IL_0072: ldloc.s a
IL_0074: stloc.s aa
IL_0076: nop
IL_0077: ldloc.s CS$5$0001
IL_0079: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_007e: stloc.s CS$4$0000
IL_0080: ldloc.s CS$4$0000
IL_0082: brtrue.s IL_004e
IL_0084: leave.s IL_00a3
} // end .try
finally
{
IL_0086: ldloc.s CS$5$0001
IL_0088: isinst [mscorlib]System.IDisposable
IL_008d: stloc.s CS$0$0002
IL_008f: ldloc.s CS$0$0002
IL_0091: ldnull
IL_0092: ceq
IL_0094: stloc.s CS$4$0000
IL_0096: ldloc.s CS$4$0000
IL_0098: brtrue.s IL_00a2
IL_009a: ldloc.s CS$0$0002
IL_009c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_00a1: nop
IL_00a2: endfinally
} // end handler
IL_00a3: nop
IL_00a4: ret
} // end of method MyIEnumberableAndIEnumberatorTest::DemoStart

...全文
141 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yan286093636 2009-06-05
  • 打赏
  • 举报
回复
学习..........
outou 2009-06-04
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zhoufoxcn 的回复:]
C# codePerson[] pe = new Person[10];
.....
foreach (Person a in po)
{
str += a.firstName + a.lastName;
Person aa = a;
}


你对一个Person数组用foreach,它使用了一些内部机制的。
[/Quote]
支持
zlb789 2009-06-04
  • 打赏
  • 举报
回复
学习
tlzjff 2009-06-04
  • 打赏
  • 举报
回复
自己顶
指间的风 2009-06-03
  • 打赏
  • 举报
回复
观赏
wuyq11 2009-06-03
  • 打赏
  • 举报
回复
IEnumerable的GetEnumerator返回一个实现了IEnumerator接口的对象
实现IEnumerable接口的类,可以支持foreach循环遍历对象的集合元素
参考
周公 2009-06-03
  • 打赏
  • 举报
回复
Person[] pe = new Person[10];
.....
foreach (Person a in po)
{
str += a.firstName + a.lastName;
Person aa = a;
}

你对一个Person数组用foreach,它使用了一些内部机制的。

17,740

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 .NET Framework
社区管理员
  • .NET Framework社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧