C#迭代器局部变量

开发 后端
这里介绍C#迭代器局部变量,IEnumerator就是C#迭代器的接口,相当于我的实例里面的Iterator,它也有泛型的版本。

C#迭代器还是比较常见的东西,这里我们主要介绍C#迭代器局部变量,包括介绍C#里出现了foreach关键字等方面。

看看***的测试,是不是不管具体的集合如何改变,遍历代码都非常稳定?而且扩展新的集合类也非常方便,只是添加代码不会修改原来的代码,符合开闭原则。当然,这么好的解决方案微软当然不会放过,现在C# 2.0里已经内置了对C#迭代器的支持,看看System.Collections, System.Collections.Generic命名空间,所有的集合都实现了这个接口:IEnumerable,这个接口还有泛型的版本。注意到这个接口只有一个方法:IEnumerator GetEnumerator();,IEnumerator就是C#迭代器的接口,相当于我的实例里面的Iterator,它也有泛型的版本。

那么现在在.net里所有的集合类都可以这样访问了:

IEnumerator ienumerator = list.GetEnumerator();  
while(ienumerator.MoveNext())  
{  
object current = ienumerator.Current;  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

但是这样访问也太麻烦了,所以C#里出现了foreach关键字,我们来看看foreach背后发生了什么

public static void Main()  
{  
ArrayList list = new ArrayList();  
list.Add(1);  
list.Add(2);  
list.Add(3);  
foreach (object item in list)  
{  
Console.WriteLine(item.ToString());  
}  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

下面是它对应的IL代码:

.method private hidebysig static void Main() cil managed  
{  
.entrypoint  
.maxstack 2  
.locals init (  
[0] class [mscorlib]System.Collections.ArrayList list,  
[1] object item,  
[2] class [mscorlib]System.Collections.IEnumerator CS$5$0000,  
[3] class [mscorlib]System.IDisposable CS$0$0001)  
L_0000: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()  
L_0005: stloc.0   
L_0006: ldloc.0   
L_0007: ldc.i4.1   
L_0008: box int32  
L_000d: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)  
L_0012: pop   
L_0013: ldloc.0   
L_0014: ldc.i4.2   
L_0015: box int32  
L_001a: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)  
L_001f: pop   
L_0020: ldloc.0   
L_0021: ldc.i4.3   
L_0022: box int32  
L_0027: callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)  
L_002c: pop   
L_002d: ldloc.0   
L_002e: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]
System.Collections.ArrayList::GetEnumerator()  
L_0033: stloc.2   
L_0034: br.s L_0048  
L_0036: ldloc.2   
L_0037: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()  
L_003c: stloc.1   
L_003d: ldloc.1   
L_003e: callvirt instance string [mscorlib]System.Object::ToString()  
L_0043: call void [mscorlib]System.Console::WriteLine(string)  
L_0048: ldloc.2   
L_0049: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()  
L_004e: brtrue.s L_0036  
L_0050: leave.s L_0063  
L_0052: ldloc.2   
L_0053: isinst [mscorlib]System.IDisposable  
L_0058: stloc.3   
L_0059: ldloc.3   
L_005a: brfalse.s L_0062  
L_005c: ldloc.3   
L_005d: callvirt instance void [mscorlib]System.IDisposable::Dispose()  
L_0062: endfinally   
L_0063: call string [mscorlib]System.Console::ReadLine()  
L_0068: pop   
L_0069: ret   
.try L_0034 to L_0052 finally handler L_0052 to L_0063  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.

从.locals init 那里可以看出编译器为我们添加了两个C#迭代器局部变量,一个就是C#迭代器。

L_002d: ldloc.0   
L_002e: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]
System.Collections.ArrayList::GetEnumerator()  
L_0033: stloc.2  
  • 1.
  • 2.
  • 3.
  • 4.

这三行代码告诉我们,调用list的GetEnumerator()方法,获取C#迭代器实例将其赋值给编译器为我们添加的那个C#迭代器局部变量,接着是L_0034: br.s L_0048,br.s这个指令是强制跳转,我们接着看

L_0048: ldloc.2   
L_0049: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() 
  • 1.
  • 2.

【编辑推荐】

  1. C# lock关键字叙述
  2. C#.Net FrameWork简介
  3. C# new和override简单描述
  4. C#值类型和引用类型浅谈
  5. C#标识符简单分析
责任编辑:佚名 来源: IT168
相关推荐

2009-08-27 10:08:36

C#隐含类型局部变量

2009-08-26 15:39:08

C#隐式类型局部变量

2009-09-17 13:05:38

Linq局部变量类型

2009-08-19 15:18:53

迭代器

2009-08-11 13:59:41

迭代器模式C# Iterator

2009-08-26 16:26:37

C#迭代器模式

2018-05-14 09:15:24

Python变量函数

2009-10-12 14:13:00

VB.NET使用局部变

2009-09-11 10:07:05

Linq隐式类型化局部

2009-12-15 10:48:54

Ruby局部变量

2020-11-11 21:26:48

函数变量

2024-05-29 08:49:22

Python全局变量局部变量

2021-09-28 07:12:09

函数内存

2015-01-07 14:41:32

Android全局变量局部变量

2010-03-15 09:32:56

Python函数

2017-02-08 12:28:37

Android变量总结

2009-09-22 17:21:24

线程局部变量

2023-09-24 23:40:54

Python变量

2009-08-18 17:17:05

C#局部类型

2010-10-14 09:34:34

JVM局部变量
点赞
收藏

51CTO技术栈公众号