目錄

          * 表達式樹練習實踐:C# 循環(huán)
          <https://www.cnblogs.com/whuanle/p/11559795.html#表達式樹練習實踐c-循環(huán)>
          * LabelTarget <https://www.cnblogs.com/whuanle/p/11559795.html#labeltarget>
          * for / while 循環(huán)
          <https://www.cnblogs.com/whuanle/p/11559795.html#for-while-循環(huán)>
          * 無限循環(huán) <https://www.cnblogs.com/whuanle/p/11559795.html#無限循環(huán)>
          * 最簡單的循環(huán) <https://www.cnblogs.com/whuanle/p/11559795.html#最簡單的循環(huán)>
          * 多次循環(huán) <https://www.cnblogs.com/whuanle/p/11559795.html#多次循環(huán)>
          * break 和 continue 一起
          <https://www.cnblogs.com/whuanle/p/11559795.html#break-和-continue-一起>
          表達式樹練習實踐:C# 循環(huán)

          C# 提供了以下幾種循環(huán)類型。

          循環(huán)類型 描述
          while 循環(huán) 當給定條件為真時,重復(fù)語句或語句組。它會在執(zhí)行循環(huán)主體之前測試條件。
          for/foreach 循環(huán) 多次執(zhí)行一個語句序列,簡化管理循環(huán)變量的代碼。
          do...while 循環(huán) 除了它是在循環(huán)主體結(jié)尾測試條件外,其他與 while 語句類似。
          嵌套循環(huán) 您可以在 while、for 或 do..while 循環(huán)內(nèi)使用一個或多個循環(huán)。
          當然,還有以下用于控制循環(huán)的語句

          控制語句 描述
          break 語句 終止 loop 或 switch 語句,程序流將繼續(xù)執(zhí)行緊接著 loop 或 switch 的下一條語句。
          continue 語句 引起循環(huán)跳過主體的剩余部分,立即重新開始測試條件。
          LabelTarget

          LabelTarget 是用于創(chuàng)建循環(huán)標記的。

          無論是 for 還是 while ,平時編寫循環(huán)時,都需要有跳出循環(huán)的判斷,有時需要某個參數(shù)自增自減并且作為判斷依據(jù)。

          C# 表達式樹里面是沒有專門表示 for /while 的,里面只有一個 Loop。看一下Loop 生成的表達式樹
          .Lambda #Lambda1<System.Func`1[System.Int32]>() { .Block(System.Int32 $x) { $x
          = 0; .Loop { .If ($x < 10) { $x++ } .Else { .Break #Label1 { $x } } }
          .LabelTarget #Label1: } }
          要實現(xiàn)循環(huán)控制,有 break,contauine 兩種 Expression:
          public static GotoExpression Break(LabelTarget target, Type type); public
          static GotoExpression Break(LabelTarget target, Expression value); public
          static GotoExpression Break(LabelTarget target); public static GotoExpression
          Break(LabelTarget target, Expression value, Type type); public static
          GotoExpression Continue(LabelTarget target, Type type); public static
          GotoExpression Continue(LabelTarget target);
          所以,要實現(xiàn)循環(huán)控制,必須要使用 LabelTarget,不然就無限循環(huán)了。

          要理解 LabelTarget ,最好的方法是動手做。

          for / while 循環(huán)

          Expression.Loop 用于創(chuàng)建循環(huán),包括 for 和 while,定義如下
          public static LoopExpression Loop(Expression body, LabelTarget @break,
          LabelTarget @continue); System.Linq.Expressions.LoopExpression. public static
          LoopExpression Loop(Expression body); public static LoopExpression
          Loop(Expression body, LabelTarget @break);
          表達式樹里面的循環(huán),只有 Loop,無 for / while 的區(qū)別。

          那么,我們來一步步理解 Loop 循環(huán)和 LabelTarget;

          無限循環(huán)
          while (true) { Console.WriteLine("無限循環(huán)"); }
          那么,對應(yīng)的 Loop 重載是這種
          public static LoopExpression Loop(Expression body)
          使用表達式樹編寫
          BlockExpression _block = Expression.Block( new ParameterExpression[] { },
          Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] {
          typeof(string) }),Expression.Constant("無限循環(huán)") ) ); LoopExpression _loop =
          Expression.Loop(_block); Expression<Action> lambda =
          Expression.Lambda<Action>(_loop); lambda.Compile()();
          最簡單的循環(huán)

          如果我想用表達式樹做到如下最簡單的循環(huán),怎么寫?
          while (true) { Console.WriteLine("我被執(zhí)行一次就結(jié)束循環(huán)了"); break; }
          表達式樹編寫
          LabelTarget _break = Expression.Label(); BlockExpression _block =
          Expression.Block( new ParameterExpression[] { }, Expression.Call(null,
          typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
          Expression.Constant("我被執(zhí)行一次就結(jié)束循環(huán)了")), Expression.Break(_break)); LoopExpression
          _loop = Expression.Loop(_block, _break); Expression<Action> lambda =
          Expression.Lambda<Action>(_loop); lambda.Compile()(); Console.ReadKey();
          生成的表達式樹
          .Lambda #Lambda1<System.Action>() { .Loop { .Block() { .Call
          System.Console.WriteLine("我被執(zhí)行一次就結(jié)束循環(huán)了"); .Break #Label1 { } } } .LabelTarget
          #Label1: }
          首先要明確,Expression.Label() 里面可以為空,它是一種標記,不參與傳遞參數(shù),不參與運算。有參無參,前后保持一致即可。

          但是上面的循環(huán)只有一次,你可以將上面的標簽改成這樣試試 LabelTarget _break = Expression.Label(typeof(int));
          ,原因后面找。

          還有, Expression.Label() 變量需要一致,否則無法跳出。

          試試一下代碼
          BlockExpression _block = Expression.Block( new ParameterExpression[] { },
          Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] {
          typeof(string) }), Expression.Constant("我被執(zhí)行一次就結(jié)束循環(huán)了")),
          Expression.Break(Expression.Label())); LoopExpression _loop =
          Expression.Loop(_block, Expression.Label()); Expression<Action> lambda =
          Expression.Lambda<Action>(_loop); lambda.Compile()(); Console.ReadKey();
          里面用到了 Expression.Block(),Block() 是塊,即{}。

          如果 Block() 是在最外層,那么相當于是函數(shù);如果是內(nèi)嵌,相當于{};

          但不是真的這樣。。。表達式樹里面不是完全按照 C# 的語法來還原操作的。

          對于 Block() 的使用,多加實踐即可。

          多次循環(huán)

          寫一個循環(huán)十次的循環(huán)語句
          for (int i = 0; i < 10; i++) { if (i < 10) { Console.WriteLine(i); } else
          break; }
          或者使用 while 表示
          int i = 0; while (true) { if (i < 10) { Console.WriteLine(i); } else break;
          i++; }
          使用表達式樹編寫
          LabelTarget _break = Expression.Label(typeof(int)); ParameterExpression a =
          Expression.Variable(typeof(int), "a"); BlockExpression _block =
          Expression.Block(new ParameterExpression[] { }, Expression.IfThenElse (
          Expression.LessThan(a, Expression.Constant(10)), Expression.Call(null,
          typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), a),
          Expression.Break(_break, a) ), Expression.PostIncrementAssign(a) // a++ );
          LoopExpression _loop = Expression.Loop(_block, _break); Expression<Action<int>>
          lambda = Expression.Lambda<Action<int>>(_loop, a); lambda.Compile()(0);
          Console.ReadKey();
          生成的表達式樹如下
          .Lambda #Lambda1<System.Action`1[System.Int32]>(System.Int32 $a) { .Loop {
          .Block() { .If ($a < 10) { .Call System.Console.WriteLine($a) } .Else { .Break
          #Label1 { $a } }; $a++ } } .LabelTarget #Label1: }
          試試將 Expression.Break(_break, a) 改成 Expression.Break(_break)??纯磮笫裁村e。。。

          解決方法是,上面的標記也改成 LabelTarget _break = Expression.Label();。

          就跟你寫代碼寫注釋一樣,里面的東西是為了讓別人看代碼是容易理解。

          有些同學糾結(jié)于 Expression.Label(有參或無參);,Expression.Break(_break, a) 與
          Expression.Break(_break),只要看看最終生成的表達式樹就清楚了。

          break 和 continue 一起

          C# 循環(huán)代碼如下
          int i = 0; while (true) { if (i < 10) { if (i % 2 == 0) {
          Console.Write("i是偶數(shù):"); Console.WriteLine(i); i++; continue; }
          Console.WriteLine("其他任務(wù) --"); Console.WriteLine("其他任務(wù) --"); } else break; i++; }
          使用 C# 表達式樹編寫(筆者將步驟詳細拆分了,所以代碼比較長)
          ParameterExpression a = Expression.Variable(typeof(int), "a"); LabelTarget
          _break = Expression.Label(); LabelTarget _continue = Expression.Label(); // if
          (i % 2 == 0) // { // Console.Write("i是偶數(shù):"); // Console.WriteLine(i); // i++;
          // continue; // } ConditionalExpression _if = Expression.IfThen(
          Expression.Equal(Expression.Modulo(a, Expression.Constant(2)),
          Expression.Constant(0)), Expression.Block( new ParameterExpression[] { },
          Expression.Call(null, typeof(Console).GetMethod("Write", new Type[] {
          typeof(string) }), Expression.Constant("i是偶數(shù):")), Expression.Call(null,
          typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), a),
          Expression.PostIncrementAssign(a), Expression.Continue(_continue) ) ); // if (i
          % 2 == 0) // { // Console.Write("i是偶數(shù):"); // Console.WriteLine(i); // i++; //
          continue; // } // Console.WriteLine("其他任務(wù) --"); // Console.WriteLine("其他任務(wù)
          --"); BlockExpression block1 = Expression.Block( new ParameterExpression[] { },
          _if, Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] {
          typeof(string) }), Expression.Constant("其他任務(wù) --")), Expression.Call(null,
          typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
          Expression.Constant("其他任務(wù) --")) ); // if (i < 10) // { // if (i % 2 == 0) // {
          // Console.Write("i是偶數(shù):"); // Console.WriteLine(i); // i++; // continue; // }
          // Console.WriteLine("其他任務(wù) --"); // Console.WriteLine("其他任務(wù) --"); // } // else
          break; ConditionalExpression if_else = Expression.IfThenElse(
          Expression.LessThan(a, Expression.Constant(10)), block1,
          Expression.Break(_break) ); // if (i < 10) // { // if (i % 2 == 0) // { //
          Console.Write("i是偶數(shù):"); // Console.WriteLine(i); // i++; // continue; // } //
          Console.WriteLine("其他任務(wù) --"); // Console.WriteLine("其他任務(wù) --"); // } // else
          break; // i++ ; BlockExpression block2 = Expression.Block( new
          ParameterExpression[] { }, if_else, Expression.PostIncrementAssign(a) ); //
          while(true) LoopExpression loop = Expression.Loop(block2, _break, _continue);
          Expression<Action<int>> lambda = Expression.Lambda<Action<int>>(loop, a);
          lambda.Compile()(0); Console.ReadKey();
          生成的表達式樹如下
          .Lambda #Lambda1<System.Action`1[System.Int32]>(System.Int32 $a) { .Loop
          .LabelTarget #Label1: { .Block() { .If ($a < 10) { .Block() { .If ( $a % 2 == 0
          ) { .Block() { .Call System.Console.Write("i是偶數(shù):"); .Call
          System.Console.WriteLine($a); $a++; .Continue #Label1 { } } } .Else {
          .Default(System.Void) }; .Call System.Console.WriteLine("其他任務(wù) --"); .Call
          System.Console.WriteLine("其他任務(wù) --") } } .Else { .Break #Label2 { } }; $a++ } }
          .LabelTarget #Label2: }
          為了便于理解,上面的代碼拆分了很多步。

          來個簡化版本
          ParameterExpression a = Expression.Variable(typeof(int), "a"); LabelTarget
          _break = Expression.Label(); LabelTarget _continue = Expression.Label();
          LoopExpression loop = Expression.Loop( Expression.Block( new
          ParameterExpression[] { }, Expression.IfThenElse( Expression.LessThan(a,
          Expression.Constant(10)), Expression.Block( new ParameterExpression[] { },
          Expression.IfThen( Expression.Equal(Expression.Modulo(a,
          Expression.Constant(2)), Expression.Constant(0)), Expression.Block( new
          ParameterExpression[] { }, Expression.Call(null,
          typeof(Console).GetMethod("Write", new Type[] { typeof(string) }),
          Expression.Constant("i是偶數(shù):")), Expression.Call(null,
          typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }), a),
          Expression.PostIncrementAssign(a), Expression.Continue(_continue) ) ),
          Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] {
          typeof(string) }), Expression.Constant("其他任務(wù) --")), Expression.Call(null,
          typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
          Expression.Constant("其他任務(wù) --")) ), Expression.Break(_break) ),
          Expression.PostIncrementAssign(a) ), _break, _continue );
          Expression<Action<int>> lambda = Expression.Lambda<Action<int>>(loop, a);
          lambda.Compile()(0); Console.ReadKey();
          需要注意的是,Expression.Break Expression.Continue 有所區(qū)別。

          當標簽實例化都是 Expression.Label() 時,
          Expression.Break(label); Expression.Continu(label);
          區(qū)別在于 continu 只能用 Expression.Label()。

          Break 可以這樣
          LabelTarget label = Expression.Label ( typeof ( int ) ); ParameterExpression a
          = Expression.Variable(typeof(int), "a"); Expression.Break ( label , a )

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                深夜久久AAAAA级毛片免费看 | 干叉视频 | 五月开心 | 爆操欧美 | 久久精品99国产精品日本 |