最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# 本地函數(shù)與 Lambda 表達式詳細介紹

 更新時間:2021年09月08日 10:49:13   作者:Vladimir Sadov  
這篇文章主要介紹了C 語言本地函數(shù)與 Lambda 表達式,,由于 C# 長期以來一直使用 lambda,因此從差異和相似之處來看本地函數(shù)確實是有意義的,感興趣的小伙伴可以參考下面文章內(nèi)容

1、C# 本地函數(shù)與 Lambda 表達式

C# 局部函數(shù)通常被視為 lambda 表達式的進一步增強。雖然功能是相關(guān)的,但也存在重大差異。

Local Functions嵌套函數(shù)]功能的 C# 實現(xiàn)。一種語言在支持 lambdas 之后獲得對嵌套函數(shù)的支持幾個版本是有點不尋常的。通常情況相反。

Lambda 或一般的一流函數(shù)需要實現(xiàn)未在堆棧上分配且生命周期與需要它們的功能對象相關(guān)聯(lián)的局部變量。如果不依賴?yán)占蛲ㄟ^捕獲列表等解決方案將變量所有權(quán)的負擔(dān)減輕給用戶,則幾乎不可能正確有效地實現(xiàn)它們。對于某些早期語言來說,這是一個嚴(yán)重的阻塞問題。嵌套函數(shù)的簡單實現(xiàn)不會遇到這種復(fù)雜情況,因此一種語言更常見的是僅支持嵌套函數(shù)而不支持 lambda。

無論如何,由于 C# 長期以來一直使用 lambda,因此從差異和相似之處來看本地函數(shù)確實是有意義的。

2、Lambda 表達式

Lambda 表達式x => x + x是抽象地表示一段代碼以及它如何綁定到其詞法環(huán)境中的參數(shù)和變量的表達式。作為代碼的抽象表示,lambda 表達式不能單獨使用。為了使用由 lambda 表達式生成的值,需要將其轉(zhuǎn)換為更多內(nèi)容,例如委托或表達式樹。

using System;
using System.Linq.Expressions;

class Program
{
    static void Main(string[] args)
    {
        // can't do much with the lambda expression directly
        // (x => x + x).ToString();  // error

        // can assign to a variable of delegate type and invoke
        Func<int, int> f = (x => x + x);
        System.Console.WriteLine(f(21)); // prints "42"

        // can assign to a variable of expression type and introspect
        Expression<Func<int, int>> e = (x => x + x);
        System.Console.WriteLine(e);     // prints "x => (x + x)"
    }
}

有幾點值得注意:

  • lambdas 是產(chǎn)生函數(shù)值的表達式。
  • lambda 值的生命周期是無限的——從 lambda 表達式的執(zhí)行開始,只要存在對該值的任何引用。這意味著 lambda 從封閉方法中使用或“捕獲”的任何局部變量都必須在堆上分配。由于 lambda 值的生命周期不受產(chǎn)生它的堆棧幀的生命周期的限制,因此不能在該堆棧幀上分配變量。
  • lambda 表達式要求在執(zhí)行 lambda 表達式時明確分配主體中使用的所有外部變量。lambda 的第一次和最后一次使用的時刻很少是確定性的,因此該語言假設(shè) lambda 值可以在創(chuàng)建后立即使用,只要它們是可訪問的。因此,一個 lambda 值在創(chuàng)建時必須是完全可用的,并且它使用的所有外部變量都必須明確分配。
        int x;

        // ERROR: 'x' is not definitely assigned
        Func<int> f = () => x;
  • lambdas 沒有名字,也不能被象征性地引用。特別是 lambda 表達式不能遞歸聲明。

注意:可以通過調(diào)用分配給 lambda 的變量或傳遞給自應(yīng)用其參數(shù)的高階方法來創(chuàng)建遞歸 lambda,但這不會表達真正的自我參照。

3、本地函數(shù)

局部函數(shù)基本上只是在另一個方法中聲明的方法,作為一種降低方法對其聲明范圍內(nèi)的可見性的方法。

自然地,局部函數(shù)中的代碼可以訪問其包含范圍內(nèi)可訪問的所有內(nèi)容——局部變量、封閉方法的參數(shù)、類型參數(shù)、局部函數(shù)。一個值得注意的例外是外部方法標(biāo)簽的可見性。封閉方法的標(biāo)簽在局部函數(shù)中不可見。這只是普通的詞法范圍,它的工作原理與 lambdas 相同。

public class C
{
    object o;

    public void M1(int p)
    {
        int l = 123;

        // lambda has access to o, p, l,
        Action a = ()=> o = (p + l);
    }

    public void M2(int p)
    {
        int l = 123;

        // Local Function has access to o, p, l,
        void a()
        {
          o = (p + l);
        }
    }
}

與 lambda 的明顯區(qū)別在于局部函數(shù)具有名稱并且可以在沒有任何間接方式的情況下使用。局部函數(shù)可以是遞歸的。

static int Fac(int arg)
{
    int FacRecursive(int a)
    {
        return a <= 1 ?
                    1 :
                    a * FacRecursive(a - 1);
    }

    return FacRecursive(arg);
}

與 lambda 表達式的主要語義區(qū)別在于局部函數(shù)不是表達式,它們是聲明語句。在代碼執(zhí)行方面,聲明是非常被動的實體。事實上,聲明并沒有真正被“執(zhí)行”。與標(biāo)簽等其他聲明類似,局部函數(shù)聲明只是將函數(shù)引入包含范圍,而無需運行任何代碼。

更重要的是,無論是聲明本身還是嵌套函數(shù)的常規(guī)調(diào)用都不會導(dǎo)致對環(huán)境的不確定捕獲。在簡單和常見的情況下,如普通的調(diào)用/返回場景,捕獲的局部變量不需要進行堆分配。

例子:

public class C
{    
    public void M()
    {
        int num = 123;

        // has access to num
        void  Nested()
        {
           num++;
        }

        Nested();

        System.Console.WriteLine(num);
    }
}

上面的代碼大致相當(dāng)于(反編譯):

public class C
{
  // A struct to hold "num" variable.
  // We are not storing it on the heap,
  // so it does not need to be a class
  private struct <>c__DisplayClass0_0
  {
      public int num;
  }

  public void M()
  {
      // reserve storage for "num" in a display struct on the _stack_
      C.<>c__DisplayClass0_0 env = default(C.<>c__DisplayClass0_0);

      // num = 123
      env.num = 123;

      // Nested()
      // note - passes env as an extra parameter
      C.<M>g__a0_0(ref env);

      // System.Console.WriteLine(num)
      Console.WriteLine(env.num);
  }

    // implementation of the the "Nested()".
    // note - takes env as an extra parameter
    // env is passed by reference so it's instance is shared
    // with the caller "M()"
    internal static void <M>g__a0_0(ref C.<>c__DisplayClass0_0 env)
    {
        env.num += 1;
    }
}

請注意,上面的代碼直接調(diào)用了“Nested()”的實現(xiàn)(不是通過委托間接),并且沒有在堆上引入顯示存儲的分配(就像 lambda 會那樣)。局部變量存儲在結(jié)構(gòu)中而不是類中。的生命周期num并沒有因為它在 中的使用而改變Nested(),所以它仍然可以在棧上分配。M()可以只通過num引用傳遞,但編譯器使用結(jié)構(gòu)體進行打包,因此它可以傳遞所有本地變量,就像num只使用一個 env 參數(shù)一樣。

另一個有趣的一點是,只要本地函數(shù)在給定范圍內(nèi)可見,就可以使用它們。這是一個重要的事實,使遞歸和相互遞歸的場景成為可能。這也使得本地函數(shù)聲明在源代碼中的確切位置在很大程度上變得不重要。

例如,封閉方法的所有變量必須在調(diào)用讀取它們的本地函數(shù)時明確分配,而不是在其聲明時。實際上,如果調(diào)用可以更早發(fā)生,那么在聲明時提出該要求將沒有任何好處。

public void M()
{
    // error here -
    // Use of unassigned local variable 'num'
    Nested();

    int num;

    // whether 'num' is assigned here or not is irrelevant
    void  Nested()
    {
       num++;
    }

    num = 123;

    // no error here - 'num' is assigned
    Nested();

    System.Console.WriteLine(num);
}

此外 - 如果從未使用過局部函數(shù),它也不會比一段無法訪問的代碼和任何變量更好,否則它會使用,不需要分配。

public void M()
{        
    int num;

    // warning - Nested() is never used.
    void  Nested()
    {
       // no errors on unassigned 'num'.
       // this code never runs.
       num++;
    }
}

4、那么,局部函數(shù)的目的是什么?

與 lambdas 相比,局部函數(shù)的主要價值主張是局部函數(shù)在概念上和運行時開銷方面都更簡單。

Lambda 可以很好地充當(dāng)一類函數(shù)的角色,但有時您只需要一個簡單的助手。分配給局部變量的 Lambda 可以完成這項工作,但存在間接開銷、委托分配和可能的閉包開銷。私有方法也有效,調(diào)用成本更低,但存在封裝問題,或缺乏封裝。這樣的助手對包含類型中的每個人都是可見的。太多這樣的幫手會導(dǎo)致嚴(yán)重的混亂。

局部函數(shù)非常適合這種情況。調(diào)用本地函數(shù)的開銷與調(diào)用私有方法的開銷相當(dāng),但使用其他不應(yīng)調(diào)用的方法污染包含類型沒有問題。

到此這篇關(guān)于C# 本地函數(shù)與 Lambda 表達式詳細介紹的文章就介紹到這了,更多相關(guān)C# 本地函數(shù)與 Lambda 表達式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Unity3D實現(xiàn)批量下載圖片功能

    Unity3D實現(xiàn)批量下載圖片功能

    這篇文章主要為大家詳細介紹了Unity3D實現(xiàn)批量下載圖片功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • C#正則表達式與HashTable詳解

    C#正則表達式與HashTable詳解

    這篇文章主要介紹了C#正則表達式與HashTable詳解,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-07-07
  • C#難點逐個擊破(5):類的訪問類型

    C#難點逐個擊破(5):類的訪問類型

    類的訪問類型有時也叫訪問級別,使用以下訪問修改符:Public、Protected、Private、internal、protected internal。
    2010-02-02
  • 詳解c# Emit技術(shù)

    詳解c# Emit技術(shù)

    這篇文章主要介紹了c# Emit技術(shù)的相關(guān)資料,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-12-12
  • C#實現(xiàn)聊天消息渲染與圖文混排詳解

    C#實現(xiàn)聊天消息渲染與圖文混排詳解

    在實現(xiàn)聊天軟件時,渲染文字表情圖文混排是一項非常繁瑣的工作,再加上還要支持GIF動圖、引用消息、撤回消息、名片等不同樣式的消息渲染時,就更加麻煩了。本文就來和大家分享一下具體實現(xiàn)方法,希望對大家有所幫助
    2023-02-02
  • C#驗證兩個QQ頭像相似度的示例代碼

    C#驗證兩個QQ頭像相似度的示例代碼

    這篇文章主要介紹了c#驗證兩個QQ頭像相似度,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • c#方法重寫和隱藏的學(xué)習(xí)示例

    c#方法重寫和隱藏的學(xué)習(xí)示例

    最近正在學(xué)習(xí)c#,對其中的方法重寫和隱藏的概念很是模糊,現(xiàn)在將其歸納如下供大家參考
    2014-01-01
  • 猜數(shù)字小游戲C#實現(xiàn)代碼

    猜數(shù)字小游戲C#實現(xiàn)代碼

    這篇文章主要為大家詳細介紹了C#實現(xiàn)猜數(shù)字小游戲的代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C#中Timer實現(xiàn)Tick使用精度的問題

    C#中Timer實現(xiàn)Tick使用精度的問題

    這篇文章主要介紹了C#中Timer實現(xiàn)Tick使用精度的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • C#畫筆Pen保存和恢復(fù)圖形對象的設(shè)置方法

    C#畫筆Pen保存和恢復(fù)圖形對象的設(shè)置方法

    這篇文章主要介紹了C#畫筆Pen保存和恢復(fù)圖形對象的設(shè)置方法,實例分析了畫筆的保存save及恢復(fù)屬性Restore的相關(guān)使用技巧,需要的朋友可以參考下
    2015-06-06

最新評論

大安市| 麻阳| 高平市| 伊金霍洛旗| 西丰县| 麟游县| 米易县| 济宁市| 东港市| 阳山县| 香河县| 大足县| 崇明县| 招远市| 苏尼特右旗| 苍梧县| 筠连县| 榆林市| 宁夏| 老河口市| 永仁县| 温宿县| 格尔木市| 图木舒克市| 五莲县| 清水河县| 平原县| 仪征市| 鄂温| 金堂县| 南皮县| 类乌齐县| 同仁县| 麻城市| 青冈县| 安宁市| 宽甸| 临漳县| 台山市| 鹿泉市| 渑池县|