2014-04-21 44 views
-1

我是C#的新手,並且正在使用這些lambda值。爲什麼我的lambda表達式不能使用相同的內部變量?

我的問題是爲什麼參數列表中的每一個都不是相同的變量?如果你注意到print(q是變量)和square(c是變量),add(x,y)是變量,而在IsLessThanTen中(f是變量),如果我想使它們全都相同參數名稱,就像比薩可以做到這一點。這是我正在觀看的教程。我的第二個小問題是,如果您不是隻使用常規函數,這會如何使代碼更好?

我認爲這些被稱爲Lambda表達式。我在教程視頻中聽到了幾個不同的名字。

問題:可以在不同的lambda表達式中使用相同的變量嗎?

我想知道,如果我可以說用我的所有拉姆達的變量索引表達式

Action<int> print = index => Console.Writeline(index); 

代碼:

Action<bool> print = q => Console.WriteLine(q); 
Func<double, double> square = c => c * c; 
Func<double, double, double> add = (x, y) => x + y; 
Predicate<double> isLessThanTen = f => f < 10; 

print(isLessThanTen(square(add(4, 5)))); 

Console.ReadKey(); 
+7

我不明白這個問題。你問你是否可以在單獨的lambda表達式中重複使用相同的變量(當然在同一個閉包之外),還是在同一個閉包中使用它?你能提供一個你認爲應該工作的例子嗎? – BradleyDotNET

回答

1

回答你的第二個問題。像這樣使用委託的好處是可以在運行時更改代表所代表的功能。

例如,假設你有multiply

Func<double, double, double> multiply = (a, b) => a * b; 

一個委託並讓我們說,你有一個瘋狂的要求,如果一定條件滿足乘除來代替。

所以......

if(crazyDemandIsMet){ 
    multiply = (a, b) => a/b; 
} 

現在,無論你用乘法,它實際上將分裂。

在這種情況下,請將multiply視爲一個變量,它包含一個函數並可以作爲函數調用。要更改此「變量」的值,必須將其分配給與您定義的簽名匹配的函數。

我曾經在一個解決方案中使用多種數據庫時使用過委託。根據數據庫是Oracle還是MS SQL,代表會有所不同。

+1

所以在現實中,您可以根據實時情況更改委託功能。所以在一種情況下,它可能會在另一種情況下增加或分開。使用常規函數你不能這樣做,但必須完全調用一個不同的函數。 –

+0

準確地說,這會產生更清晰的代碼。另外,請記住,您不必使用lambda。您也可以將一個聲明的函數分配給委託,只要它與簽名匹配即可。 – Smeegs

1

沒錯,拉姆達參數名稱可以重複使用和重複變量名不會衝突「跨越」兄弟Lambda Expressions(又名匿名函數)..

Action<bool> print = q => Console.WriteLine(q); 
Func<double, double> square = q => q * q; 
Func<double, double, double> add = (q, q2) => q + q2; 
Predicate<double> isLessThanTen = q => q < 10; 

..即使它可以導致更難瞭解代碼!正如Servy所說,

當然,如果每個參數在概念上表示相同的東西,那麼使用相同的參數名稱是好的。 它使用相同的參數名稱來表示完全不同的事情,這是一個問題。

即,在每個拉姆達的q單獨變量,即使它們共享相同的名稱。


現在,有不允許的,主要是在用相同的名稱的變量在範圍存在(在問題的命名共享在兄弟範圍)的情況。例如,

int q = 0; 
Action<bool> print = q => Console.WriteLine(q); 

導致編譯器錯誤

命名爲「Q」的局部變量不能在此範圍 聲明,因爲它會給予不同的意義,「Q」,這已經是在'父或當前'範圍內使用 來表示其他內容。


lambda表達式的一些大的好處,因爲相比於普通的方法:

  1. Lambda表達式表達式可以導致Expression Trees - 這是背後L2S/EF的魔力。
  2. 與普通方法相比,lambda可以充當閉包並捕獲自由變量。
  3. 甜甜的糖。在LINQ查詢中應用上述內容時非常有用。
+0

當然,如果每個參數在概念上代表相同的東西,那麼使用相同的參數名稱就沒有問題。它使用相同的參數名稱來表示完全不同的事情,這是一個問題。 – Servy

+0

@Servy非常好。我引用了你的評論。 – user2864740

1

您可以在不同的lambda表達式中使用相同的變量名,但它們必須在包含它們的方法中是唯一的。例如:

void SomeFunction() 
{ 
    int i; 
    Func<int, int> timesTwo = i => i * 2; // Bad. Conflicts with other variable 
} 

至於你的其他問題,他們是否比常規方法更好,這是完全主觀的,他們都有自己的位置。

+0

根據我的測試,lambda也比函數調用更快,因爲他們已經是代表 – Gusman

+1

@Gusman錯誤和錯誤。 Lambdas不是代表。它們是用於創建委託實例的一種可能的語法。 Lambdas將被編譯爲命名方法,就像任何其他命名方法一樣;該名稱只是在編譯代碼之前不知道。您不會知道名稱是什麼,但該方法實際上在運行時會有一個名稱。以某種方式測試有缺陷的可能性非常高;要麼你沒有比較等效的操作,要麼你不恰當地測量它們。兩者都很容易做到,因爲基準測試是一件很難做到的事情。 – Servy

+0

沒有,經過多次測試,因爲我期待着oposite的結果,並且調用lambda函數(或函數的委託)更快。我的意思是「委託」是你將從委託中使用它(當你將它賦值給一個委託創建的變量時),你不能稱之爲純函數。 – Gusman

0

您可以對所有的lambda方法使用相同的變量名稱。

 Action<bool>     method1 = i => Console.WriteLine(i); 
     Func<double, double>   method2 = i => i * i; 
     Func<double, double, double> method3 = (i, i2) => i + i2/i * i *40; 
     Predicate<double>   method4 = i => i < 2000; 

你不能有一個名爲i的局部變量,這會導致命名轉換。人們使用這些類型的表達式的原因是因爲他們在某些情況下,速度更快,你可以根據條件

 Action<int> method1 = i => Console.WriteLine(i + 3); 

     if (test == 3) 
      method1 = i => Console.WriteLine(i + i); 
     else if (test == 2) 
      method1 = i => Console.WriteLine(i + i + i); 
     Console.ReadKey(); 

你看方法1以上上述已有定義,但根據測試改變他們的飛行導致方法1可以改變爲不同的東西。如果你願意,你可以用兩種不同的方法做同樣的事情。我有時不確定是否應該使用這種類型的示例。我已經在代碼中看到過它,但坦率地說,我決定何時使用它是很奇怪的,因爲你可以像上面的例子一樣在你的代碼中運行。

相關問題