亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C#中的using和yieldreturn混合使用

2019-11-14 16:45:01
字體:
來源:轉載
供稿:網友

      最近寫代碼為了為了省事兒用了幾個yield return,因為我不想New一個List<T>或者T[]對象再往里放元素,就直接返回IEnumerable<T>了。我的代碼里還有很多需要Dispose的對象,所以又用了幾個using。寫著寫著我有點心虛了——這樣混合使用靠譜嗎?

     今天我花時間研究一下,并在這里作個筆記,跟大家分享。筆者水平有限,有哪些理解錯誤或做的不到位的地方,還請各位專家點撥。

     這是我寫的方法,循環外面一個using,整個方法里代碼執行后釋放一個對象。循環里面又一個using, 每次循環yield return后要釋放一個對象。那是不是任何情況下這些[被創建了的需要釋放的]DisposableObject對象最后都會被釋放呢?

        PRivate static IEnumerable<int> GetNumbers(int count)        {            using (DisposableObject parentDisposableObject = new DisposableObject("ParentDisposableObject"))            {                foreach (int number in Enumerable.Range(1, count))                {                    using (DisposableObject childDisposableObject = new DisposableObject(string.Format("ChildDisposableObject{0}", number)))                    {                        //if (number == 4)                        //{                        //    throw new Exception("異常。");                        //}                        if (number != 2)                        {                            yield return number * 10;                        }                        else                        {                            Console.WriteLine(" 循環{0} else 代碼執行了", number.ToString());                        }                        Console.WriteLine(" 循環{0}else下面的代碼執行了", number.ToString());                    }                }            }        }            }

 

     需要釋放資源的類定義如下,創建對象和釋放時都有輸出。

class DisposableObject : IDisposable    {        private string _value;        public DisposableObject(string value)        {            _value = value;            Console.WriteLine("Create Object {0}", _value);        }        public void Dispose()        {            Console.WriteLine("Disposable Object {0}", _value);        }    }

    這里調用下:

        static void Main(string[] args)        {            foreach (int number in GetNumbers(5))            {                Console.WriteLine("結果 {0}", number.ToString());            }        }

 

    看看運行結果:

    

     我們可以看到:1、循環外面的對象和循環里面的DisposableObject對象都被釋放了,這個讓我很高興,要的就是這個效果;2,如果yield return后面還有代碼,[yield] return后還會繼續執行;3,if-else有作用,不滿足條件可以不把該項作為結果返回,不想執行某段代碼可以放{}里。這個運行的結果我很滿意,就是我想要的!

     下面我把拋異常的代碼注釋去掉,看看循環內拋出的異常后能否正常釋放對象。

     結果很完美,擔憂是多余的,該釋放的DisposableObject對象都被釋放了!

     那么我們簡單研究下yield return吧,我寫了下面最簡單的代碼:

                private static IEnumerable<int> GetNumbers(int[] numbers)        {            foreach (int number in numbers)            {                yield return number*10;            }        }        

      把項目編譯再反編譯成C#2.0,發現代碼變成了這個樣子:

private static IEnumerable<int> GetNumbers(int[] numbers){    <GetNumbers>d__0 d__ = new <GetNumbers>d__0(-2);    d__.<>3__numbers = numbers;    return d__;}  


     這里的<GetNumbers>d__0是個自動生成的類(看來這是高熱量的語法糖,吃的是少了,程序集卻發胖了?。?,它實現了IEnumerable<T>,IEnumerator<T>等接口,而上面方法其實就是返回了一個封裝了迭代器塊代碼的計數對象而已,如果您僅僅調用了一下上面這個方法,它可能不會執行循環中的代碼,除非觸發了返回值的MoveNext方法,這就是傳說中的延遲求值吧!

[CompilerGenerated]private sealed class <GetNumbers>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable{    // Fields    private int <>1__state;    private int <>2__current;    public int[] <>3__numbers;    public int[] <>7__wrap3;    public int <>7__wrap4;    private int <>l__initialThreadId;    public int <number>5__1;    public int[] numbers;    // Methods    [DebuggerHidden]    public <GetNumbers>d__0(int <>1__state);    private void <>m__Finally2();    private bool MoveNext();    [DebuggerHidden]    IEnumerator<int> IEnumerable<int>.GetEnumerator();    [DebuggerHidden]    IEnumerator IEnumerable.GetEnumerator();    [DebuggerHidden]    void IEnumerator.Reset();    void IDisposable.Dispose();    // Properties    int IEnumerator<int>.Current { [DebuggerHidden] get; }    object IEnumerator.Current { [DebuggerHidden] get; }} Expand Methods 
View Code

     通過MSIL查看上面的foreach循環會調用MoveNext方法。

entrypoint    .maxstack 2    .locals init (        [0] int32 number,        [1] class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> CS$5$0000)    L_0000: ldc.i4.5     L_0001: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> Consoleapplication1.Program::GetNumbers(int32)    L_0006: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()    L_000b: stloc.1     L_000c: br.s L_0026    L_000e: ldloc.1     L_000f: callvirt instance !0 [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()    L_0014: stloc.0     L_0015: ldstr "/u7ed3/u679c/uff1a{0}"    L_001a: ldloca.s number    L_001c: call instance string [mscorlib]System.Int32::ToString()    L_0021: call void [mscorlib]System.Console::WriteLine(string, object)    L_0026: ldloc.1     L_0027: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()    L_002c: brtrue.s L_000e    L_002e: leave.s L_003a    L_0030: ldloc.1     L_0031: brfalse.s L_0039    L_0033: ldloc.1     L_0034: callvirt instance void [mscorlib]System.IDisposable::Dispose()    L_0039: endfinally     L_003a: ret     .try L_000c to L_0030 finally handler L_0030 to L_003a
View Code

    而循環里面的執行內容都在MoveNext方法里。

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();    }}  
View Code

     接著再看下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     fault48     {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             try34             {35                 switch (this.<>1__state)36                 {37                     case 2:38                     case 3:39                     case 4:40                         try41                         {42                             switch (this.<>1__state)43                             {44                                 case 3:45                                 case 4:46                                     try47                                     {48                                     }49                                     finally50                                     {51                                         this.<>m__Finally7();52                                     }53                                     break;54                             }55                         }56                         finally57                         {58                             this.<>m__Finally6();59                         }60                         break;61                 }62             }63             finally64             {65                 this.<>m__Finally4();66             }67             break;68 69         default:70             return;71     }72 }

     

 


上一篇:IOC

下一篇:寫給女程序員的一篇文章

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
992tv成人免费视频| 亚洲国产日韩欧美在线图片| 久久久免费高清电视剧观看| 亚洲天堂av在线播放| 在线播放国产精品| 国产精品视频网| 亚洲欧美日韩一区二区三区在线| 精品久久久久久久久久久久| 国产一区二区三区在线播放免费观看| 91精品国产综合久久男男| 91国产美女视频| 日韩精品极品毛片系列视频| 国内精品久久久久久中文字幕| 亚洲免费人成在线视频观看| 欧美黑人巨大精品一区二区| 国产日韩欧美中文在线播放| 亚洲第一视频网| 国产精品久久久久久久久男| 亚洲激情第一页| 17婷婷久久www| 97超级碰碰碰久久久| y97精品国产97久久久久久| 日韩一区二区福利| 亚洲精品v欧美精品v日韩精品| 久久精品99久久香蕉国产色戒| 欧美另类老肥妇| 国产91免费看片| 久久69精品久久久久久久电影好| 日韩av在线免费| 奇米一区二区三区四区久久| 久久综合伊人77777尤物| 久久中文字幕在线| 亚洲第一综合天堂另类专| 久久精品一偷一偷国产| 国产精品视频中文字幕91| 91免费观看网站| 久久精品国产v日韩v亚洲| 97久久精品国产| 亚洲成人激情图| 国产精品中文字幕在线观看| 日韩在线视频免费观看高清中文| 欧美激情在线观看| 亚洲欧美日韩一区二区在线| 亚洲色图50p| 91av在线看| 欧美日韩亚洲视频| 国产成人精品a视频一区www| 久久免费精品视频| 亚洲欧美国产一本综合首页| 欧美性视频精品| 波霸ol色综合久久| 国产精品欧美一区二区三区奶水| 日日摸夜夜添一区| 色噜噜国产精品视频一区二区| 日韩电影中文字幕在线观看| 日韩不卡在线观看| 日韩欧美国产成人| 日韩欧美在线网址| 久久久噜噜噜久久中文字免| yw.139尤物在线精品视频| 久久影视电视剧免费网站| 亚洲国产美女精品久久久久∴| 欧美另类极品videosbestfree| 亚洲福利视频网| 美日韩丰满少妇在线观看| 亚洲人成亚洲人成在线观看| 亚洲色图狂野欧美| 成人av在线网址| 亚洲天堂av在线免费观看| 欧美性猛交xxxx| 久久久久久久电影一区| 精品国产精品三级精品av网址| 成人写真福利网| 77777少妇光屁股久久一区| 久久黄色av网站| 久久精品国产亚洲精品2020| 成人激情春色网| 久久69精品久久久久久久电影好| 亚洲一区二区三区四区在线播放| 欧美刺激性大交免费视频| 日本久久亚洲电影| 欧美极品少妇xxxxⅹ免费视频| 亚洲黄色成人网| 91欧美精品午夜性色福利在线| 午夜精品视频在线| 亚洲片av在线| 久久久久久久97| 国产精品主播视频| 精品久久久久久久久久久久久久| 91精品美女在线| 日韩av成人在线| 亚洲网址你懂得| 91在线观看免费高清| 国产精品久久9| 美女久久久久久久| 久久精品99国产精品酒店日本| 国产精品盗摄久久久| 精品精品国产国产自在线| 欧美综合国产精品久久丁香| 国产精品劲爆视频| 77777亚洲午夜久久多人| 欧美日韩国产成人在线| 在线播放国产一区二区三区| 久久久久久久久久久网站| 欧美专区国产专区| 91久久久精品| 久久精品国产亚洲精品2020| 欧美精品午夜视频| 成人激情电影一区二区| 国产精品av免费在线观看| 成人黄色av网| 国产美女精品视频免费观看| 九九久久久久久久久激情| 久久久久久97| 国产精品久久久一区| 亚洲丝袜一区在线| 日本亚洲欧洲色α| 一级做a爰片久久毛片美女图片| 国产精品视频久久| 国产精品中文久久久久久久| 人人澡人人澡人人看欧美| 日韩中文字幕亚洲| 美日韩在线视频| 成人做爰www免费看视频网站| 久久久久久com| 欧美色视频日本版| 久久中文字幕视频| 欧洲s码亚洲m码精品一区| 亚洲大尺度美女在线| 黄色成人av网| 国产欧洲精品视频| 久久久91精品| 成人久久一区二区三区| 亚洲欧美一区二区三区久久| 超薄丝袜一区二区| 成人国产亚洲精品a区天堂华泰| 国产婷婷成人久久av免费高清| 久久精品国产成人精品| 日韩视频免费中文字幕| 亚洲欧美制服丝袜| 亚洲男女自偷自拍图片另类| 成人午夜黄色影院| 在线精品高清中文字幕| 成人国产亚洲精品a区天堂华泰| 中文字幕日韩精品有码视频| 91精品综合视频| 欧美在线视频免费观看| 日本精品一区二区三区在线播放视频| 亚洲激情在线观看视频免费| 午夜精品蜜臀一区二区三区免费| 亚洲欧美www| 91日本在线视频| 国产欧美精品一区二区三区介绍| 8050国产精品久久久久久| 黑人与娇小精品av专区| 亚洲一区中文字幕在线观看| 亚洲字幕在线观看| 亚洲人成毛片在线播放| 国产成人亚洲综合91精品| 久久久久久中文| 热久久这里只有精品| 国产精品稀缺呦系列在线| 国产69精品久久久久99| 91精品视频专区|