C#中的using和yield return混合使用
2014-04-05 10:07
274 查看
最近写代码为了为了省事儿用了几个yield return,因为我不想New一个List<T>或者T[]对象再往里放元素,就直接返回IEnumerable<T>了。我的代码里还有很多需要Dispose的对象,所以又用了几个using。写着写着我有点心虚了——这样混合使用靠谱吗?
今天我花时间研究一下,并在这里作个笔记,跟大家分享。笔者水平有限,有哪些理解错误或做的不到位的地方,还请各位专家点拨。
这是我写的方法,循环外面一个using,整个方法里代码执行后释放一个对象。循环里面又一个using, 每次循环yield return后要释放一个对象。那是不是任何情况下这些[被创建了的需要释放的]DisposableObject对象最后都会被释放呢?
接着再看下using,也来个最简单的。
然后我们看一下对应的MSIL:
再换一种C#写法试试:
对应的MSIL代码:
看看两段MSIL多像啊,特别是最后一句!
最后我们看看yield return 和 using混合使用时,自动生成的<GetNumbers>d__0类是如何保证需要释放资源的DisposableObject对象被释放的,看后我不禁感慨:C#的编译器真是鬼斧神工啊!
今天我花时间研究一下,并在这里作个笔记,跟大家分享。笔者水平有限,有哪些理解错误或做的不到位的地方,还请各位专家点拨。
这是我写的方法,循环外面一个using,整个方法里代码执行后释放一个对象。循环里面又一个using, 每次循环yield return后要释放一个对象。那是不是任何情况下这些[被创建了的需要释放的]DisposableObject对象最后都会被释放呢?
private bool MoveNext() { try { switch (this.<>1__state) { case 0: this.<>1__state = -1; this.<parentDisposableObject>5__1 = new DisposableObject("ParentDisposableObject"); this.<>1__state = 1; this.<>7__wrap5 = Enumerable.Range(1, this.count).GetEnumerator(); this.<>1__state = 2; while (this.<>7__wrap5.MoveNext()) { this.<number>5__2 = this.<>7__wrap5.Current; this.<childDisposableObject>5__3 = new DisposableObject(string.Format("ChildDisposableObject{0}", this.<number>5__2)); this.<>1__state = 3; if (this.<number>5__2 == 4) { throw new Exception("异常。"); } if (this.<number>5__2 == 2) { goto Label_00D0; } this.<>2__current = this.<number>5__2 * 10; this.<>1__state = 4; return true; Label_00C7: this.<>1__state = 3; goto Label_00E8; Label_00D0: Console.WriteLine("循环{0}:else 内代码执行了 ", this.<number>5__2.ToString()); Label_00E8: Console.WriteLine("循环{0}:else下面的代码执行了 ", this.<number>5__2.ToString()); this.<>m__Finally7(); } this.<>m__Finally6(); this.<>m__Finally4(); break; case 4: goto Label_00C7; } return false; } fault { this.System.IDisposable.Dispose(); } }
接着再看下using,也来个最简单的。
using (DisposableObject parentDisposableObject = new DisposableObject("MainDisposableObject")) { Console.WriteLine("执行..."); //throw new Exception("异常。"); }
然后我们看一下对应的MSIL:
.entrypoint .maxstack 1 .locals init ( [0] class ConsoleApplication1.DisposableObject parentDisposableObject) L_0000: ldstr "MainDisposableObject" L_0005: newobj instance void ConsoleApplication1.DisposableObject::.ctor(string) L_000a: stloc.0 L_000b: ldstr "\u6267\u884c..." L_0010: call void [mscorlib]System.Console::WriteLine(string) L_0015: leave.s L_0021 L_0017: ldloc.0 L_0018: brfalse.s L_0020 L_001a: ldloc.0 L_001b: callvirt instance void [mscorlib]System.IDisposable::Dispose() L_0020: endfinally L_0021: ret .try L_000b to L_0017 finally handler L_0017 to L_0021
再换一种C#写法试试:
DisposableObject parentDisposableObject = new DisposableObject("MainDisposableObject"); try { Console.WriteLine("执行..."); //throw new Exception("异常。"); } finally { parentDisposableObject.Dispose(); }
对应的MSIL代码:
.entrypoint .maxstack 1 .locals init ( [0] class ConsoleApplication1.DisposableObject parentDisposableObject) L_0000: ldstr "MainDisposableObject" L_0005: newobj instance void ConsoleApplication1.DisposableObject::.ctor(string) L_000a: stloc.0 L_000b: ldstr "\u6267\u884c..." L_0010: call void [mscorlib]System.Console::WriteLine(string) L_0015: leave.s L_001e L_0017: ldloc.0 L_0018: callvirt instance void ConsoleApplication1.DisposableObject::Dispose() L_001d: endfinally L_001e: ret .try L_000b to L_0017 finally handler L_0017 to L_001e
看看两段MSIL多像啊,特别是最后一句!
最后我们看看yield return 和 using混合使用时,自动生成的<GetNumbers>d__0类是如何保证需要释放资源的DisposableObject对象被释放的,看后我不禁感慨:C#的编译器真是鬼斧神工啊!
1 private bool MoveNext() 2 { 3 try 4 { 5 switch (this.<>1__state) 6 { 7 case 0: 8 this.<>1__state = -1; 9 this.<parentDisposableObject>5__1 = new DisposableObject("ParentDisposableObject"); 10 this.<>1__state = 1; 11 this.<>7__wrap5 = Enumerable.Range(1, this.count).GetEnumerator(); 12 this.<>1__state = 2; 13 while (this.<>7__wrap5.MoveNext()) 14 { 15 this.<number>5__2 = this.<>7__wrap5.Current; 16 this.<childDisposableObject>5__3 = new DisposableObject(string.Format("ChildDisposableObject{0}", this.<number>5__2)); 17 this.<>1__state = 3; 18 if (this.<number>5__2 == 4) 19 { 20 throw new Exception("异常。"); 21 } 22 if (this.<number>5__2 == 2) 23 { 24 goto Label_00D0; 25 } 26 this.<>2__current = this.<number>5__2 * 10; 27 this.<>1__state = 4; 28 return true; 29 Label_00C7: 30 this.<>1__state = 3; 31 goto Label_00E8; 32 Label_00D0: 33 Console.WriteLine("循环{0}:else 内代码执行了 ", this.<number>5__2.ToString()); 34 Label_00E8: 35 Console.WriteLine("循环{0}:else下面的代码执行了 ", this.<number>5__2.ToString()); 36 this.<>m__Finally7(); 37 } 38 this.<>m__Finally6(); 39 this.<>m__Finally4(); 40 break; 41 42 case 4: 43 goto Label_00C7; 44 } 45 return false; 46 } 47 fault 48 { 49 this.System.IDisposable.Dispose(); 50 } 51 } 52 53 54 55
1 public DisposableObject <parentDisposableObject>5__1; 2 3 4 public DisposableObject <childDisposableObject>5__3; 5 6 7 private void <>m__Finally4() 8 { 9 this.<>1__state = -1; 10 if (this.<parentDisposableObject>5__1 != null) 11 { 12 this.<parentDisposableObject>5__1.Dispose(); 13 } 14 } 15 16 private void <>m__Finally7() 17 { 18 this.<>1__state = 2; 19 if (this.<childDisposableObject>5__3 != null) 20 { 21 this.<childDisposableObject>5__3.Dispose(); 22 } 23 } 24 25 void IDisposable.Dispose() 26 { 27 switch (this.<>1__state) 28 { 29 case 1: 30 case 2: 31 case 3: 32 case 4: 33 try 34 { 35 switch (this.<>1__state) 36 { 37 case 2: 38 case 3: 39 case 4: 40 try 41 { 42 switch (this.<>1__state) 43 { 44 case 3: 45 case 4: 46 try 47 { 48 } 49 finally 50 { 51 this.<>m__Finally7(); 52 } 53 break; 54 } 55 } 56 finally 57 { 58 this.<>m__Finally6(); 59 } 60 break; 61 } 62 } 63 finally 64 { 65 this.<>m__Finally4(); 66 } 67 break; 68 69 default: 70 return; 71 } 72 }
相关文章推荐
- C#中的using和yield return混合使用
- C#中的using和yield return混合使用
- [存底]使用C#压缩/解压缩7-zip文件 zip/Unzip file using 7-zip in C#
- C# using 三种使用方式
- C# using 三种使用方式
- C#中using的使用
- C# using语句使用心得总结
- 使用vs2005创建智能设备的C#和C++混合项目
- C#中using的使用方法
- C# using 三种使用方式
- using关键字在C#中的使用方法
- C# using 三种使用方式
- 提高C#编程水平的50个要点 之十五“使用 using 和 try-finally 来处理资源的释放”
- C# using 三种使用方式
- C#与C++的混合编程 之二 使用非托管dll 导出标准函数
- C# using(){}使用地方
- C#--- IEnumerable<T>和yield return的使用
- C# using 三种使用方式 zhuan
- C#中is,as,using关键字的使用
- 【转】C# using的三种使用方法