2016-12-03 47 views
73

我期待在新的實現中C# 7.0,我覺得它很有趣,他們已經實現了本地功能,但我無法想象其中本地功能將優於lambda表達式的情景,什麼是兩者的區別。局部功能VS LAMBDA C#7.0

我也明白,lambda表達式是anonymous功能同時局部功能都沒有,但我不能想出一個真實的場景,其中本地函數有超過拉姆達優勢表達式

任何例如將不勝感激。謝謝。

+4

泛型,輸出參數,遞歸函數,而無需初始化拉姆達爲空,等 –

+3

@KirkWoll - 你應該張貼此作爲一個答案。 – Enigmativity

回答

137

This was explained by Mads Torgersen in C# Design Meeting Notes where local functions were first discussed

你想要一個輔助函數。您只能在一個函數內使用它,並且它可能使用包含該函數的範圍內的變量和類型參數。另一方面,與lambda不同,你並不需要它作爲第一類對象,所以你不需要給它一個委託類型並分配一個實際的委託對象。你也可能希望它是遞歸或通用的,或者將它作爲迭代器來實現。

在其上擴展更多一些,其優點是:

  1. 性能。

    當創建一個拉姆達,委託必須創建,這是在這種情況下的不必要的分配。本地功能實際上只是功能,沒有代表是必要的。

    此外,本地功能與捕獲局部變量更有效:lambda表達式通常捕獲變量成一個類,而本地函數可以使用一個結構,它再次避免了分配(使用ref傳遞)。

    這也意味着調用本地函數是便宜,所以他們可以被內聯,甚至可能進一步提高性能。

  2. 本地函數可以是遞歸的。

    Lambdas也可以遞歸,但它需要笨拙的代碼,首先將null分配給委託變量,然後分配lambda。局部函數自然可以遞歸(包括相互遞歸)。

  3. 本地函數可以是通用的。

    Lambda表達式不能通用,因爲它們必須被分配給一個變量與一個具體類型(該類型可以使用通用的變量從外部範圍,但是這不是一回事)。

  4. 本地功能可以被實現爲一個迭代。

    Lambda表達式不能使用yield return(和yield break)關鍵字來實現IEnumerable<T> -returning功能。本地功能可以。

  5. 本地功能看起來更好。

    這不是在以上報價提到的,並且可能只是我個人的偏見,但我認爲正常功能語法看起來不是一個委託變量分配拉姆達更好。本地功能也更加簡潔。

    比較:

    int add(int x, int y) => x + y; 
    Func<int, int, int> add = (x, y) => x + y; 
    
+3

非常明確,感謝您花一些時間回答:) – Sid

+2

我想補充說,本地函數在調用方有參數名稱。蘭姆達斯不會。 – Lensflare

+1

@Lensflare確實沒有保留lambda表達式的參數名稱,但這是因爲它們必須轉換爲具有自己名稱的代表。例如:'Func f =(x,y)=> x + y; f(arg1:1,arg2:1);'。 – svick

37

除了svick's great answer還有一個優勢,本地功能:
他們可以在函數的任何位置來定義,即使是return語句之後。

public double DoMath(double a, double b) 
{ 
    var resultA = f(a); 
    var resultB = f(b); 
    return resultA + resultB; 

    double f(double x) => 5 * x + 3; 
}