徹底搞懂C#之Yield Return語法的作用和好處
還是和以前一樣,我先上程式碼,請大家先拿到我的程式碼或者你跟著敲,執行看效果,以及理解每行帶程式碼的作用。
我們要帶著為什麼要用Yield這個關鍵字,不用可以嗎這個目的去學知識,我相信會更加的有意思。
首先我貼出平時正常輸出偶數集合的辦法
/*
*
* 學習Yield Return 語法
* 使用兩個方法,顯示1 - 100之間的全部偶數
*
*
*/
using System;
using System.Collections.Generic;
namespace YieldReturn語法解析
{
class Program
{
static private List<int> _numArray; //用來儲存1-100 這100個整數
Program() //建構函式。我們可以通過這個建構函式往待測試集合中存入1-100這100個測試資料
{
_numArray = new List<int>(); //給集合變數開始在堆記憶體上開記憶體,並且把記憶體首地址交給這個_numArray變數
for (int i = 1; i <= 100; i++)
{
_numArray.Add(i); //把1到100儲存在集合當中方便操作
}
}
static void Main(string[] args)
{
new Program();
TestMethod();
}
//測試求1到100之間的全部偶數
static public void TestMethod()
{
foreach (var item in GetAllEvenNumber())
{
Console.WriteLine(item); //輸出偶數測試
}
}
//測試我們正常情況下拿到全部偶數的方法
static IEnumerable<int> GetAllEvenNumber()
{
List<int> result = new List<int>(); //開集合記憶體存偶數用
foreach (int num in _numArray)
{
if(num % 2 == 0) //判斷是不是偶數
{
//yield return num;
result.Add(num); //存入集合
}
}
//返回偶數集合變數 可能有人會覺得奇怪返回型別不是List<int>這樣可以嗎
//這個就要回到我們的里氏替換原則了,子類是可以替換父類的,也就是當父類用
//比如我這個方法是想得到IEnumerable<int> 型別變數,但是我給了List<int>型別變數
//注意List<int> 是繼承 IEnumerable<int> 的,什麼意思當我們把子類當父類使用,
//那麼大才小用,因為子類很多都是繼承父親,你自身增加很多欄位或者方法,這樣就不能用了。
return result;
//yield break;
}
}
}
貼出使用Yiele Return辦法輸出耦合集合
/*
*
* 學習Yield Return 語法
* 使用兩個方法,顯示1 - 100之間的全部偶數
*
*
*/
using System;
using System.Collections.Generic;
namespace YieldReturn語法解析
{
class Program
{
static private List<int> _numArray; //用來儲存1-100 這100個整數
Program() //建構函式。我們可以通過這個建構函式往待測試集合中存入1-100這100個測試資料
{
_numArray = new List<int>(); //給集合變數開始在堆記憶體上開記憶體,並且把記憶體首地址交給這個_numArray變數
for (int i = 1; i <= 100; i++)
{
_numArray.Add(i); //把1到100儲存在集合當中方便操作
}
}
static void Main(string[] args)
{
new Program();
TestMethod();
}
//測試求1到100之間的全部偶數
static public void TestMethod()
{
foreach (var item in GetAllEvenNumber())
{
Console.WriteLine(item); //輸出偶數測試
}
}
//測試我們使用Yield Return情況下拿到全部偶數的方法
static IEnumerable<int> GetAllEvenNumber()
{
foreach (int num in _numArray)
{
if(num % 2 == 0) //判斷是不是偶數
{
yield return num; //返回當前偶數
}
}
yield break; //當前集合已經遍歷完畢,我們就跳出當前函式,其實你不加也可以
//這個作用就是提前結束當前函式,就是說這個函式執行完畢了。
}
}
}
大家測試了2個程式碼結果沒,是不是都可以正確拿到全部偶數集合,具體我需要你們測,這樣進步快,才會真是學會。只看不練假把戲。
現在我們說他們的區別:
這個才是真正要學的地方
我們需要下斷點
我希望你是在斷點除錯,具體就貼太多,你會發現程式碼跑到Yield return num的時候,當前函式就會結束,並把這個num交給這裡,我先上圖
最終會給item變數。
然後輸出,然後在執行 GetAllEvenNumber()方法,和上次得到偶數是一樣。
我們發現這個Yield Return是可以讓當前函式的程序狀態切換到阻塞狀態,然後去選擇了把cpu交給當前的出程序,這樣就轉而執行呼叫方函式。 (補充個小知識點其實我們寫的程式加入到記憶體中,並不定就是一個程序,我們會根據情況分成幾個子程序去幹活,方便作業系統去管理以及多道程式執行在記憶體,提高計算機資源的利用率)
這樣有個好處,我們假如有1000000個數據,我們需要得到裡面的耦合,當我們通過這個方法得到一個耦合會立馬顯示在控制檯上。而不是等很久也就把全部偶數都查詢到存入集合當中,然後在一一遍歷輸出。
這個好處是很大的。比如我們使用者可能就看資料開始肯定不是全部值需要部分就可以,看完這些在看後面的,這樣資料會讓覺得顯示沒有延遲。
下面我們來斷點調一般的查詢偶數的函式
我們發現這個迴圈沒有跑完是不會退出當前函式的,也就是必須要查詢全部的偶數才可以。這樣假如我們很多資料。就會一直等這個資料才可以拿到這個資料去顯示給使用者看。
這樣就麻煩了。
因此我們下個結論:Yield Return關鍵字的作用就是退出當前函式,並且會儲存當前函式執行到什麼地方,也就上下文。你發現沒下次執行這個函式上次跑來的程式碼是不會重複執行的,
但是你一般的return result 假如你在迴圈體提前return ,下面調這個函式是會從第一步開始重新執行的。不會記錄上次執行的地方。