C# yield關鍵字


關於yield關鍵字,網上有很多文章介紹了,但是看了之后,雖然明白了"哦,原來是這么回事",但是在日常開發中並沒有真正的用起來,所以,寫此一篇,介紹一下在真正的項目中怎么使用這個關鍵字。

開始我的正文介紹之前,可以先看一下微軟的官方文檔是怎么介紹yield關鍵字的,傳送門:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/yield

在這里我新建了一個控制台程序,用於輸出斐波那契數列,代碼如下:我們直接在Main方法中輸出斐波那契數列,這個也沒有什么問題,很完美,但是考慮到實際開發中不可能把所有的處理都寫在程序入口,所以我們考慮對這段代碼封裝一個方法V1

static void Main(string[] args)
{int a = 0, b = 1, c = 0;
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("{0}", b);
        c = a + b;
        a = b;
        b = c;
    }

    //V1(10);

    //foreach (var i in V2(10))
    //{
    //    Console.WriteLine(i);
    //}

    //foreach (var i in V3(10))
    //{
    //    Console.WriteLine(i);
    //}

    Console.ReadKey();
}

方法V1代碼如下:與Main方法中的代碼段是一模一樣的,那么有經驗的同學肯定會想,既然已經封裝了方法,那么方法的輸出應該封裝成返回值,返回給Main方法,然后再輸出到控制台,於是我們再次修改,封裝成方法V2

private static void V1(int number)
{
    Console.WriteLine("V1");
    int a = 0, b = 1, c = 0;
    for (int i = 0; i < number; i++)
    {
        Console.WriteLine("{0}", b);
        c = a + b;
        a = b;
        b = c;
    }
}

方法V2代碼如下:方法V2中創建了一個List<int>的列表,用來接收方法返回的結果,然后在Main方法中輸出。那么這里有什么問題呢?問題就是如果循環的基數很大,那么,我們的List中的item就很大,占用內存也會隨之增加,於是,我們在此基礎上再次改造成方法V3

private static IEnumerable<int> V2(int number)
{
    Console.WriteLine("V2");
    List<int> vs = new List<int>();
    int a = 0, b = 1, c = 0;
    for (int i = 0; i < number; i++)
    {
        vs.Add(b);
        c = a + b;
        a = b;
        b = c;
    }
    return vs;
}

方法V3代碼如下:這里便用到了關鍵字yield,正如官方文檔中所述,迭代器方法運行到 yield return 語句時,會返回一個 expression,並保留當前在代碼中的位置。 下次調用迭代器函數時,將從該位置重新開始執行。這樣的話,內存不會隨着基數的增加而增加,而效果卻是一模一樣的。

private static IEnumerable<int> V3(int number)
{
    Console.WriteLine("V3");
    int a = 0, b = 1, c = 0;
    for (int i = 0; i < number; i++)
    {
        yield return b;
        c = a + b;
        a = b;
        b = c;
    }
}

那么,總結經驗,在你需要返回一個繼承自IEnumerable的集合類型的時候,就可以使用這個yield關鍵字了。

最后的運行效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM