c# c#學習筆記-委派與lambda表示式 - C#Lambda表達式:為什麼我應該使用它們?





lambda是什麼 lambda範例 (13)


很多時候,你只能在一個地方使用這個功能,所以製作一個方法會讓整個班級變得混亂。

我已經快速閱讀了Microsoft Lambda Expression文檔。

雖然這樣的例子幫助我更好地理解:

delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25

不過,我不明白為什麼這是一種創新。 這只是一個方法,當“方法變量”結束時就會死掉,對嗎? 為什麼我應該使用這個而不是真正的方法?




微軟為我們提供了一種更簡潔,更便捷的方式來創建名為Lambda表達式的匿名代理。 但是,對這個聲明的表達部分沒有太多關注。 微軟發布了一個完整的命名空間System.Linq.Expressions ,它包含了基於lambda表達式創建表達式樹的類。 表達式樹由表示邏輯的對象組成。 例如,x = y + z是一個表達式,可能是.Net中表達式樹的一部分。 考慮以下(簡單)示例:

using System;
using System.Linq;
using System.Linq.Expressions;


namespace ExpressionTreeThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<int, int>> expr = (x) => x + 1; //this is not a delegate, but an object
            var del = expr.Compile(); //compiles the object to a CLR delegate, at runtime
            Console.WriteLine(del(5)); //we are just invoking a delegate at this point
            Console.ReadKey();
        }
    }
}

這個例子很簡單。 我相信你在想:“這是無用的,因為我可以直接創建委託,而不是創建表達式並在運行時編譯它。” 你會是對的。 但是這為表達樹提供了基礎。 Expressions命名空間中有許多可用的表達式,您可以構建自己的表達式。 我想你可以看到,當你不知道算法在設計或編譯時應該是什麼時,這可能是有用的。 我在某個地方看到了使用它編寫科學計算器的例子。 您也可以將其用於Bayesian系統或遺傳編程 (AI)。 在我的職業生涯中,我不得不編寫類似Excel的功能,允許用戶輸入簡單的表達式(添加,刪除等)來操作可用數據。 在pre.Net 3.5中,我不得不求助於C#外部的某種腳本語言,或者必須在反射中使用代碼發射功能來即時創建.Net代碼。 現在我會使用表達式樹。




您還可以在編寫泛型代碼時使用lambda表達式來處理您的方法。

例如:通用函數來計算方法調用所花費的時間。 (即Action在這裡)

public static long Measure(Action action)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    action();
    sw.Stop();
    return sw.ElapsedMilliseconds;
}

您可以使用lambda表達式調用上述方法,如下所示,

var timeTaken = Measure(() => yourMethod(param));

表達式允許你從你的方法中獲得返回值,並且還可以獲得參數

var timeTaken = Measure(() => returnValue = yourMethod(param, out outParam));



這只是使用lambda表達式的一種方式。 您可以在任何可以使用委託的地方使用lambda表達式。 這可以讓你做這樣的事情:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

strings.Find(s => s == "hello");

此代碼將在列表中搜索與單詞“hello”匹配的條目。 另一種做法是實際將代理傳遞給Find方法,如下所示:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

private static bool FindHello(String s)
{
    return s == "hello";
}

strings.Find(FindHello);

編輯

在C#2.0中,這可以使用匿名委託語法完成:

  strings.Find(delegate(String s) { return s == "hello"; });

Lambda大大清理了這種語法。




例如,Lambda清理了C#2.0的匿名委託語法

Strings.Find(s => s == "hello");

這是在C#2.0中完成的:

Strings.Find(delegate(String s) { return s == "hello"; });

在功能上,他們做的是完全相同的事情,它只是一個更簡潔的語法。




這是一種採取小操作的方式,並將其與使用位置非常接近(與聲明接近其使用點的變量不同)。 這應該讓你的代碼更具可讀性。 通過對錶達式進行匿名處理,如果某個人在其他地方使用了該功能並將其修改為“增強”該功能,那麼對於某人破壞客戶端代碼而言,也會使其變得更加困難。

同樣,為什麼你需要使用foreach? 您可以使用plain for循環執行foreach中的所有操作,也可以直接使用IEnumerable。 答:你不需要它,但它使你的代碼更具可讀性。




Lambda表達式是表示匿名方法的簡明方式。 匿名方法和Lambda表達式都允許您以內聯方式定義方法實現,但是,匿名方法明確要求您為方法定義參數類型和返回類型。 Lambda表達式使用C#3.0的類型推斷功能,它允許編譯器根據上下文來推斷變量的類型。 這是非常方便的,因為這節省了我們很多打字!




lambda表達式就像代替委託實例寫入的匿名方法。

delegate int MyDelagate (int i);
MyDelagate delSquareFunction = x => x * x;

考慮lambda表達式x => x * x;

輸入參數值是x(在=>的左側)

函數邏輯是x * x(在=>的右側)

lambda表達式的代碼可以是語句塊而不是表達式。

x => {return x * x;};

注意: Func是一個預定義的泛型委託。

    Console.WriteLine(MyMethod(x => "Hi " + x));

    public static string MyMethod(Func<string, string> strategy)
    {
        return strategy("Lijo").ToString();
    }

參考

  1. 代表和接口如何互換使用?



創新在於安全性和透明度。 儘管您沒有聲明lambda表達式的類型,但它們被推斷出來,並且可以被代碼搜索,靜態分析,重構工具和運行時反射使用。

例如,在您可能使用過SQL並可能獲得SQL注入攻擊之前,因為黑客在正常情況下需要傳遞一個字符串。 現在你將使用一個LINQ lambda表達式,它受到保護。

在純代理上構建LINQ API是不可能的,因為它需要在評估它們之前將表達式樹組合在一起。

在2016年,大多數流行的語言都支持lambda表達式 ,C#是這種演進中主流命令式語言的先驅之一。




匿名函數和表達式對於一次性方法非常有用,它不會從創建完整方法所需的額外工作中受益。

考慮這個例子:

 string person = people.Find(person => person.Contains("Joe"));

 public string FindPerson(string nameContains, List<string> persons)
 {
     foreach (string person in persons)
         if (person.Contains(nameContains))
             return person;
     return null;
 }

這些在功能上是等同的。




這也許是為什麼使用lambda表達式的最好解釋 - > https://youtu.be/j9nj5dTo54Q

總之,這是為了提高代碼的可讀性,通過重複使用而不是複制代碼來減少錯誤的機會,並利用幕後的優化。




它節省了必須在特定位置只使用一次的方法遠離他們使用的地方。 好的用途是比較排序等通用算法的比較器,然後可以在調用排序時定義自定義排序函數,而不是遠離強迫您查看其他位置以查看排序內容。

這不是一項真正的創新。 LISP具有約30年或更長時間的lambda功能。




事務(不使用TransactionScope)





c# c#-3.0 lambda