您的位置:首页 > 编程语言 > C#

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对象最后都会被释放呢?



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 }


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: