C#中的using和yield return混合使用.docx

上传人:b****3 文档编号:3753236 上传时间:2022-11-25 格式:DOCX 页数:16 大小:169.51KB
下载 相关 举报
C#中的using和yield return混合使用.docx_第1页
第1页 / 共16页
C#中的using和yield return混合使用.docx_第2页
第2页 / 共16页
C#中的using和yield return混合使用.docx_第3页
第3页 / 共16页
C#中的using和yield return混合使用.docx_第4页
第4页 / 共16页
C#中的using和yield return混合使用.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

C#中的using和yield return混合使用.docx

《C#中的using和yield return混合使用.docx》由会员分享,可在线阅读,更多相关《C#中的using和yield return混合使用.docx(16页珍藏版)》请在冰豆网上搜索。

C#中的using和yield return混合使用.docx

C#中的using和yieldreturn混合使用

     最近写代码为了为了省事儿用了几个yieldreturn,因为我不想New一个List或者T[]对象再往里放元素,就直接返回IEnumerable了。

我的代码里还有很多需要Dispose的对象,所以又用了几个using。

写着写着我有点心虚了——这样混合使用靠谱吗?

    今天我花时间研究一下,并在这里作个笔记,跟大家分享。

笔者水平有限,有哪些理解错误或做的不到位的地方,还请各位专家点拨。

   这是我写的方法,循环外面一个using,整个方法里代码执行后释放一个对象。

循环里面又一个using,每次循环yieldreturn后要释放一个对象。

那是不是任何情况下这些[被创建了的需要释放的]DisposableObject对象最后都会被释放呢?

privatestaticIEnumerableGetNumbers(intcount)

{

using(DisposableObjectparentDisposableObject=newDisposableObject("ParentDisposableObject"))

{

foreach(intnumberinEnumerable.Range(1,count))

{

using(DisposableObjectchildDisposableObject=newDisposableObject(string.Format("ChildDisposableObject{0}",number)))

{

//if(number==4)

//{

//thrownewException("异常。

");

//}

if(number!

=2)

{

yieldreturnnumber*10;

}

else

{

Console.WriteLine("循环{0}else代码执行了",number.ToString());

}

Console.WriteLine("循环{0}else下面的代码执行了",number.ToString());

}

}

}

}

}

 

    需要释放资源的类定义如下,创建对象和释放时都有输出。

classDisposableObject:

IDisposable

{

privatestring_value;

publicDisposableObject(stringvalue)

{

_value=value;

Console.WriteLine("CreateObject{0}",_value);

}

publicvoidDispose()

{

Console.WriteLine("DisposableObject{0}",_value);

}

}

    这里调用下:

staticvoidMain(string[]args)

{

foreach(intnumberinGetNumbers(5))

{

Console.WriteLine("结果{0}",number.ToString());

}

}

 

   看看运行结果:

    

    我们可以看到:

1、循环外面的对象和循环里面的DisposableObject对象都被释放了,这个让我很高兴,要的就是这个效果;2,如果yieldreturn后面还有代码,[yield]return后还会继续执行;3,if-else有作用,不满足条件可以不把该项作为结果返回,不想执行某段代码可以放{}里。

这个运行的结果我很满意,就是我想要的!

    下面我把抛异常的代码注释去掉,看看循环内抛出的异常后能否正常释放对象。

     结果很完美,担忧是多余的,该释放的DisposableObject对象都被释放了!

    那么我们简单研究下yieldreturn吧,我写了下面最简单的代码:

privatestaticIEnumerableGetNumbers(int[]numbers)

{

foreach(intnumberinnumbers)

{

yieldreturnnumber*10;

}

}

     把项目编译再反编译成C#2.0,发现代码变成了这个样子:

privatestaticIEnumerableGetNumbers(int[]numbers)

{

d__0d__=newd__0(-2);

d__.<>3__numbers=numbers;

returnd__;

}

    这里的d__0是个自动生成的类(看来这是高热量的语法糖,吃的是少了,程序集却发胖了!

),它实现了IEnumerable,IEnumerator等接口,而上面方法其实就是返回了一个封装了迭代器块代码的计数对象而已,如果您仅仅调用了一下上面这个方法,它可能不会执行循环中的代码,除非触发了返回值的MoveNext方法,这就是传说中的延迟求值吧!

[CompilerGenerated]

privatesealedclassd__0:

IEnumerable,IEnumerable,IEnumerator,IEnumerator,IDisposable

{

//Fields

privateint<>1__state;

privateint<>2__current;

publicint[]<>3__numbers;

publicint[]<>7__wrap3;

publicint<>7__wrap4;

privateint<>l__initialThreadId;

publicint5__1;

publicint[]numbers;

//Methods

[DebuggerHidden]

publicd__0(int<>1__state);

privatevoid<>m__Finally2();

privateboolMoveNext();

[DebuggerHidden]

IEnumeratorIEnumerable.GetEnumerator();

[DebuggerHidden]

IEnumeratorIEnumerable.GetEnumerator();

[DebuggerHidden]

voidIEnumerator.Reset();

voidIDisposable.Dispose();

//Properties

intIEnumerator.Current{[DebuggerHidden]get;}

objectIEnumerator.Current{[DebuggerHidden]get;}

}

ExpandMethods

ViewCode

    通过MSIL查看上面的foreach循环会调用MoveNext方法。

entrypoint

.maxstack2

.localsinit(

[0]int32number,

[1]class[mscorlib]System.Collections.Generic.IEnumerator`1CS$5$0000)

L_0000:

ldc.i4.5

L_0001:

callclass[mscorlib]System.Collections.Generic.IEnumerable`1ConsoleApplication1.Program:

:

GetNumbers(int32)

L_0006:

callvirtinstanceclass[mscorlib]System.Collections.Generic.IEnumerator`1

0>[mscorlib]System.Collections.Generic.IEnumerable`1:

:

GetEnumerator()

L_000b:

stloc.1

L_000c:

br.sL_0026

L_000e:

ldloc.1

L_000f:

callvirtinstance!

0[mscorlib]System.Collections.Generic.IEnumerator`1:

:

get_Current()

L_0014:

stloc.0

L_0015:

ldstr"\u7ed3\u679c\uff1a{0}"

L_001a:

ldloca.snumber

L_001c:

callinstancestring[mscorlib]System.Int32:

:

ToString()

L_0021:

callvoid[mscorlib]System.Console:

:

WriteLine(string,object)

L_0026:

ldloc.1

L_0027:

callvirtinstancebool[mscorlib]System.Collections.IEnumerator:

:

MoveNext()

L_002c:

brtrue.sL_000e

L_002e:

leave.sL_003a

L_0030:

ldloc.1

L_0031:

brfalse.sL_0039

L_0033:

ldloc.1

L_0034:

callvirtinstancevoid[mscorlib]System.IDisposable:

:

Dispose()

L_0039:

endfinally

L_003a:

ret

.tryL_000ctoL_0030finallyhandlerL_0030toL_003a

ViewCode

   而循环里面的执行内容都在MoveNext方法里。

privateboolMoveNext()

{

try

{

switch(this.<>1__state)

{

case0:

this.<>1__state=-1;

this.5__1=newDisposableObject("ParentDisposableObject");

this.<>1__state=1;

this.<>7__wrap5=Enumerable.Range(1,this.count).GetEnumerator();

this.<>1__state=2;

while(this.<>7__wrap5.MoveNext())

{

this.5__2=this.<>7__wrap5.Current;

this.5__3=newDisposableObject(string.Format("ChildDisposableObject{0}",this.5__2));

this.<>1__state=3;

if(this.5__2==4)

{

thrownewException("异常。

");

}

if(this.5__2==2)

{

gotoLabel_00D0;

}

this.<>2__current=this.5__2*10;

this.<>1__state=4;

returntrue;

Label_00C7:

this.<>1__state=3;

gotoLabel_00E8;

Label_00D0:

Console.WriteLine("循环{0}:

else内代码执行了",this.5__2.ToString());

Label_00E8:

Console.WriteLine("循环{0}:

else下面的代码执行了",this.5__2.ToString());

this.<>m__Finally7();

}

this.<>m__Finally6();

this.<>m__Finally4();

break;

case4:

gotoLabel_00C7;

}

returnfalse;

}

fault

{

this.System.IDisposable.Dispose();

}

}

ViewCode

    接着再看下using,也来个最简单的。

using(DisposableObjectparentDisposableObject=newDisposableObject("MainDisposableObject"))

{

Console.WriteLine("执行...");

//thrownewException("异常。

");

}

     然后我们看一下对应的MSIL:

.entrypoint

.maxstack1

.localsinit(

[0]classConsoleApplication1.DisposableObjectparentDisposableObject)

L_0000:

ldstr"MainDisposableObject"

L_0005:

newobjinstancevoidConsoleApplication1.DisposableObject:

:

.ctor(string)

L_000a:

stloc.0

L_000b:

ldstr"\u6267\u884c..."

L_0010:

callvoid[mscorlib]System.Console:

:

WriteLine(string)

L_0015:

leave.sL_0021

L_0017:

ldloc.0

L_0018:

brfalse.sL_0020

L_001a:

ldloc.0

L_001b:

callvirtinstancevoid[mscorlib]System.IDisposable:

:

Dispose()

L_0020:

endfinally

L_0021:

ret

.tryL_000btoL_0017finallyhandlerL_0017toL_0021

    再换一种C#写法试试:

DisposableObjectparentDisposableObject=newDisposableObject("MainDisposableObject");

try

{

Console.WriteLine("执行...");

//thrownewException("异常。

");

}

finally

{

parentDisposableObject.Dispose();

}

    对应的MSIL代码:

.entrypoint

.maxstack1

.localsinit(

[0]classConsoleApplication1.DisposableObjectparentDisposableObject)

L_0000:

ldstr"MainDisposableObject"

L_0005:

newobjinstancevoidConsoleApplication1.DisposableObject:

:

.ctor(string)

L_000a:

stloc.0

L_000b:

ldstr"\u6267\u884c..."

L_0010:

callvoid[mscorlib]System.Console:

:

WriteLine(string)

L_0015:

leave.sL_001e

L_0017:

ldloc.0

L_0018:

callvirtinstancevoidConsoleApplication1.DisposableObject:

:

Dispose()

L_001d:

endfinally

L_001e:

ret

.tryL_000btoL_0017finallyhandlerL_0017toL_001e

    看看两段MSIL多像啊,特别是最后一句!

    最后我们看看yieldreturn和using混合使用时,自动生成的d__0类是如何保证需要释放资源的DisposableObject对象被释放的,看后我不禁感慨:

C#的编译器真是鬼斧神工啊!

1privateboolMoveNext()

2{

3try

4{

5switch(this.<>1__state)

6{

7case0:

8this.<>1__state=-1;

9this.5__1=newDisposableObject("ParentDisposableObject");

10this.<>1__state=1;

11this.<>7__wrap5=Enumerable.Range(1,this.count).GetEnumerator();

12this.<>1__state=2;

13while(this.<>7__wrap5.MoveNext())

14{

15this.5__2=this.<>7__wrap5.Current;

16this.5__3=newDisposableObject(string.Format("ChildDisposableObject{0}",this.5__2));

17this.<>1__state=3;

18if(this.5__2==4)

19{

20thrownewException("异常。

");

21}

22if(this.5__2==2)

23{

24gotoLabel_00D0;

25}

26this.<>2__current=this.5__2*10;

27this.<>1__state=4;

28returntrue;

29Label_00C7:

30this.<>1__state=3;

31gotoLabel_00E8;

32Label_00D0:

33Console.WriteLine("循环{0}:

else内代码执行了",this.5__2.ToString());

34Label_00E8:

35Console.WriteLine("循环{0}:

else下面的代码执行了",this.5__2.ToString());

36this.<>m__Finally7();

37}

38this.<>m__Finally6();

39this.<>m__Finally4();

40break;

41

42case4:

43gotoLabel_00C7;

44}

45returnfalse;

46}

47fault

48{

49this.System.IDisposable.Dispose();

50}

51}

52

53

54

55

1publicDisposableObject5__1;

2

3

4publicDisposableObject5__3;

5

6

7privatevoid<>m__Finally4()

8{

9this.<>1__state=-1;

10if(this.5__1!

=null)

11{

12this.5__1.Dispose();

13}

14}

15

16privatevoid<>m__Finally7()

17{

18this.<>1__state=2;

19if(this.5__3!

=null)

20{

21this.5__3.Dispose();

22}

23}

24

25voidIDisposable.Dispose()

26{

27switch(this.<>1__state)

28{

29case1:

30case2:

31case3:

32case4:

33try

34{

35switch(this.<>1__state)

36{

37case2:

38case3:

39case4:

40try

41{

42switch(this.<>1__state)

43{

44case3:

45case4:

46try

47{

48}

49finally

50{

51this.<>m__Finally7();

52}

53break;

54}

55}

56finally

57{

58this.<>m__Finally6();

59}

60break;

61}

62}

63finally

64{

65this.<>m__Finally4();

66}

67break;

68

69default:

70return;

71}

72}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 电力水利

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1