1. 程式人生 > >C#中的yield return與Unity中的Coroutine(協程)(上)

C#中的yield return與Unity中的Coroutine(協程)(上)

C#中的yield return

C#語法中有個特別的關鍵字yield, 它是幹什麼用的呢?

來看看專業的解釋:

yield 是在迭代器塊中用於向列舉數物件提供值或發出迭代結束訊號。它的形式為下列之一:
yield return <expression>;
yield break

看如下例子:

 1  1     public class CustomCollection :IEnumerable {
 2  2         
 3  3         public static void Main (string[] args)
 4  4         {
5 5 CustomCollection cc = new CustomCollection (); 6 6 7 7 foreach (String word in cc) { 8 8 Console.WriteLine ("word:" +word); 9 9 } 10 10 } 11 11 12 12 public IEnumerator GetEnumerator(){ 13 13 14 14 yield
return "Hello"; 15 15 yield return "Boys"; 16 16 yield return "And"; 17 17 yield return "Girls"; 18 18 //return new HelloBoyGirls(); 19 19 20 20 } 21 21 } 22 22 23 23 // public class HelloBoyGirls: IEnumerator { 24 24 // private int cusor = -1;
25 25 // private String[] words = {"Hello", "Boys", "And", "Girls"}; 26 26 // 27 27 // public bool MoveNext () 28 28 // { 29 29 // cusor++; 30 30 // return cusor < words.Length; 31 31 // } 32 32 // 33 33 // public void Reset () 34 34 // { 35 35 // cusor = 0; 36 36 // } 37 37 // 38 38 // public object Current { 39 39 // get { 40 40 // return words [cusor]; 41 41 // } 42 42 // } 43 43 // }
View Code

上面的例子是實現了一個自定義的迭代器;實現可迭代(可以用foreach)的資料集合,必須實現GetEmumerator()方法,返回實現了IEmumerator的物件例項。

完成這個, 有兩種方法,一種是用上面註釋掉的程式碼,一種是用yield return. yield return 需要配合IEmumerator進行使用, 在外部foreach迴圈中,它會執行GetEmumerator()方法,遇到yield return, 做了如下兩件事情:

1.記錄下當前執行到的程式碼位置

2. 將程式碼控制權返回到外部, yield return 後面的值, 作為迭代的當前值。

當執行下一個迴圈, 從剛才記錄的程式碼位置後面, 開始繼續執行程式碼。

簡單地說, yield return 就是實現IEmumerator的超級簡化版, 是不是很簡單?

那麼問題又來了, yield return 是如何決定迴圈該結束,yield return 之後的程式碼, 什麼時候執行呢?

把上面的例子改造一下, 不要用方便的foreach了, 用while 迴圈自己控制:

 1     public class CustomCollection :IEnumerable {
 2         
 3         public static void Main (string[] args)
 4         {
 5             CustomCollection cc = new CustomCollection ();
 6 
 7             IEnumerator enumerator = cc.GetEnumerator ();
 8             while (true) {
 9                 bool canMoveNext = enumerator.MoveNext ();
10                 Console.WriteLine ("canMoveNext:" +canMoveNext);
11                 if (!canMoveNext)
12                     break;
13                 Object obj = enumerator.Current;
14                 Console.WriteLine ("current obj:" +obj);
15             }
16 //            foreach (String word in cc) {
17 //                Console.WriteLine ("word:" +word);
18 //            }
19             Console.WriteLine ("Main End.");
20 
21         }
22 
23         public IEnumerator GetEnumerator(){
24 
25             yield return "Hello";
26             yield return "Boys";
27             yield return "And";
28             yield return "Girls";
29 
30             Console.WriteLine ("After all yield returns.");
31             //return new HelloBoyGirls();
32 
33         }
34     }
View Code

執行程式碼, 結果是:

canMoveNext:True
current obj:Hello
canMoveNext:True
current obj:Boys
canMoveNext:True
current obj:And
canMoveNext:True
current obj:Girls
After all yield returns.
canMoveNext:False
Main End.

說明, 在GetEmumerator()中, 只有yield return 語句, 外部呼叫MoveNext()都為true, current就是yield return後面的物件

除了yield return, 還有yield break; yield break 的作用是, 停止迴圈, MoveNext()為false, yield break 之後的語句, 不會被執行!

有興趣的童鞋, 可以自己寫個例子試試。

相關推薦

C#yield returnUnityCoroutine

C#中的yield return C#語法中有個特別的關鍵字yield, 它是幹什麼用的呢? 來看看專業的解釋: yield 是在迭代器塊中用於向列舉數物件提供值或發出迭代結束訊號。它的形式為下列之一:yield return <expression>;yield break 看如下例

關於C#迭代器UnityCoroutine

微軟的官方文件:迭代器是C#2.0中的新功能,迭代器是方法、get訪問器或運算子,使你能在類或結構體中支援foreach迭代,而不必實現整個IEnumerable介面,只需提供一個迭代器,即可遍歷類中的資料結構,當編譯器檢測到迭代器時,它將自動生成IEnumerable或IEnumerable<T&g

C#yield return的用法示例

tel namespace ole tar spa int bsp enume con using System; using System.Collections.Generic; namespace YieldReturn { class Program

C#unitybase64string和圖片互轉

C#: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using

c++的訊號QML的函式繫結(連結)起來 以及qmlc++互動重要筆記

signals: Q_INVOKABLE void buttonLeft();     Q_INVOKABLE void buttonRight();     Q_INVOKABLE void buttonShort();    Q_INVOKABLE void butto

c#datetime型別SqlServerdatetime格式的區別

一直以為c#中datetime與SqlServer中datetime類似,直到今日偶然發現兩者之間的格式是有區別的。 c#日期(圖1) 從上面的圖中我們可以看到c#的日期格式是帶星期的。 SQLServer日期(圖2) SqlServer的日期格式是不帶星期的。

C#的委託Java的介面回撥

  最近因為業務需求學習起了C#,對於學過Java的人來說,C#其實還是挺好懂的,基本上很多語法都是相通的。今天就談談我對C#和Java中不同的地方的理解吧。   說到Java中的介面回撥那麼就不得不提觀察者設計模式,所謂觀察者模式就是A(觀察者 Observ

Web服務器之Tomcat的相關說明Web訪問的角色協議問題和JavaWeb項目的程序結構問題

b/s架構 c/s架構 context.xml說明 server.xml說明 javaweb項目的程序結構 1、C/S架構和B/S架構的概念:a、C/S架構:- C/S,Client/Server,客戶端/服務器,客戶端需要安裝專用的客戶端軟件。客戶端是針對某以具體業務專門開發的軟件。-

使用C#的Conditional特性Unity編輯器宏命令做條件編譯

運行時 符號 unit log edit ext 通過 space 編譯 概要 在傳統的C#項目中,用Conditional特性做條件編譯時,需要在Visual Studio中項目的屬性裏添加上條件編譯符號,用法參考這篇文章。 而在Unity項目中,條件編譯符號需要在Uni

python的__new____init__,新式類和經典類2.x)

類型 pytho 圖片 pla object pri lba 版本 其它 在python2.x中,從object繼承得來的類稱為新式類(如class A(object))不從object繼承得來的類稱為經典類(如class A()) 新式類跟經典類的差別主要是以下幾點: 

javaScript的onclickjquery的click區別

mce 上下 要點 let 怎樣 報錯 ron n) 屬性 來來來,先看一個例子: html部分,定義幾個按鈕 <div class="carousel-btn"> <button class="btn"></button>

虛擬機器下ubuntu檔案實現windows檔案共享

第一步  在Ubuntu選單上選擇VM->install VMware tools。然後出現VMware tools的安裝壓縮包檔案VMwareTools-9.2.0-799703.tar.gz。 第二步 可以先將該壓縮檔案複製到主資料夾下,然後解壓tar.gz

Python“i+=ii=i+i”的區別梳理:引用、記憶體、可變引數、不可變引數

Python中“i+=i與i=i+i”的區別梳理 一、 "i+=i"執行時資料記憶體的變化 當num+=num執行時,num原引用的記憶體空間中,根據空間中儲存的引數的資料型別是否為可變型別而進行變化,***可變的引數資料型別***有:列表、字典;***不可變引

當ROS的cv2anaconda3的cv2衝突時的解決辦法

今天心血來潮, 想用Anaconda3中的Python3.6.4跑一個opencv小例子, 結果出人意料,出現了ROS中的/opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so檔案, 顯然這個是行不通的嘛, 然後我

獲取json的keyvalue的方法

String res = "{"_index":"k12oos","_type":"exercise","_id":"-0WtGG1FhQSmqIQhKU8pMg","_version":2,"found":true,"_source":{"code":"1009430255","stageId":"go2L

JS的onloadjQuery的ready區別

jQuery的執行機制(onload與ready的區別) 結論得出前自行測試: 為了測試是否真如所說的那樣,所以在頁面插入了20000張照片,照片數量少得不出什麼結論,所以改用console.log

Object的tostringArray的tostring的區別?

Object 類的 toString 方法返回一個字串,該字串由類名(物件是該類的一個例項)、at  標記符“@”和此物件雜湊碼的無符號十六進位制表示組成。Arrays的toString方法是返回指定陣列內容的字串表示形式。 兩者是重名函式關係,沒有複寫。 從意會的角度講,這就好比羊喝水和你喝水一

ES5的varES6的let,const的區別

1、ES5中使用var來宣告變數,會產生作用域提升的問題。例: var a=1; function scope(){ console.log(a); var a=2; } scope(); //得到的結果既不是1也不是2,是undefined

jface databinding:使用CheckboxTableViewer實現表(Set)物件CheckTable選中條目資料繫結

上一篇博文《jface databinding:可多選的widget List元件selection專案與java.util.List物件的雙向資料繫結》講述瞭如何實現List元件的多選項與List資料繫結的問題。 實際使用中覺得用List元件來給使用者做多選

獲取瀏覽器語言的完美方案。各瀏覽器對 navigator 物件幾個語言相關的屬性的返回值存在差異

標準參考 無 問題描述 各瀏覽器對 navigator 物件中幾個與語言相關的屬性(language、userLanguage、browserLanguage、 systemLanguage)的返回值存在很大的差異。 造成的影響 由於不同瀏覽器對這幾個屬性的返回值有很