[C#] C # Lambda 표현식 : 왜 사용해야합니까?

Microsoft Lambda Expression 설명서를 빨리 읽었습니다 .

그러나 이런 종류의 예는 다음과 같이 더 잘 이해하는 데 도움이되었습니다.

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

그래도 왜 그런 혁신인지 이해할 수 없습니다. “메소드 변수”가 끝나면 죽는 방법 일뿐입니다. 실제 방법 대신 왜 이것을 사용해야합니까?



답변

람다 식은 익명 대리자의 간단한 구문이며 익명 대리자가 사용될 수있는 모든 곳에서 사용할 수 있습니다. 그러나 그 반대는 사실이 아닙니다. 람다 식은 LINQ to SQL과 같은 많은 마법을 허용하는 식 트리로 변환 될 수 있습니다.

다음은 익명 대리자를 사용하고 람다 식을 사용하여 LINQ to Objects 표현식 의 예입니다 .

// anonymous delegate
var evens = Enumerable
                .Range(1, 100)
                .Where(delegate(int x) { return (x % 2) == 0; })
                .ToList();

// lambda expression
var evens = Enumerable
                .Range(1, 100)
                .Where(x => (x % 2) == 0)
                .ToList();

Lambda 표현식과 익명 델리게이트는 별도의 함수를 작성하는 것보다 이점 이 있습니다. 클로저 를 구현 하면 함수에 매개 변수추가 하거나 일회용 객체를 만들지 않고도 로컬 상태를 함수전달할 수 있습니다.

식 트리는 C # 3.0의 매우 강력한 새로운 기능으로, API가 실행할 수있는 메서드에 대한 참조를 얻는 대신 식의 구조를 볼 수 있도록합니다. API는 대리자 매개 변수를 매개 변수로 만들면 Expression<T>컴파일러가 익명 ​​대리자 대신 람다에서 식 트리를 생성합니다.

void Example(Predicate<int> aDelegate);

처럼 호출 :

Example(x => x > 5);

된다 :

void Example(Expression<Predicate<int>> expressionTree);

후자는 표현식을 설명하는 추상 구문 트리 의 표현을 전달 받게됩니다 x > 5. LINQ to SQL은 C # 표현식을 서버 측에서 필터링 / 순서 등으로 원하는 SQL 표현식으로 변환 할 수 있도록이 동작에 의존합니다.


답변

익명 함수 및 표현식은 전체 메소드를 작성하는 데 필요한 추가 작업의 이점이없는 일회성 메소드에 유용합니다.

이 예제를 고려하십시오.

 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;
 }

이들은 기능적으로 동일합니다.


답변

다른 컨트롤을 사용하여 일부 컨트롤의 이벤트에 대한 핸들러를 선언하려는 상황에서 유용하다는 것을 알았습니다. 일반적으로 컨트롤의 참조를 클래스의 필드에 저장하여 생성 된 것과 다른 방법으로 사용할 수 있도록해야합니다.

private ComboBox combo;
private Label label;

public CreateControls()
{
    combo = new ComboBox();
    label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
}

void combo_SelectedIndexChanged(object sender, EventArgs e)
{
    label.Text = combo.SelectedValue;
}

람다 식 덕분에 다음과 같이 사용할 수 있습니다.

public CreateControls()
{
    ComboBox combo = new ComboBox();
    Label label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += (s, e) => {label.Text = combo.SelectedValue;};
}

훨씬 쉽게.


답변

Lambda는 C # 2.0의 익명 대리자 구문을 정리했습니다.

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

C # 2.0에서 다음과 같이 수행되었습니다.

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

기능적으로 그들은 똑같은 일을합니다. 단지 훨씬 간결한 구문입니다.


답변

이것은 람다 식을 사용하는 한 가지 방법입니다. 델리게이트를 사용할 수있는 곳이면 람다 식을 사용할 수 있습니다. 이를 통해 다음과 같은 작업을 수행 할 수 있습니다.

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"; });

람다는 구문을 크게 정리했습니다.


답변

Microsoft는 Lambda 식이라는 익명의 대리자를 만드는보다 깨끗하고 편리한 방법을 제공했습니다. 그러나, 이 진술 의 표현 부분 에는 많은주의를 기울이지 않습니다 . Microsoft는 람다 식을 기반으로 식 트리를 만드는 클래스가 포함 된 전체 네임 스페이스 인 System.Linq.Expressions를 릴리스했습니다 . 식 트리는 논리를 나타내는 개체로 구성됩니다. 예를 들어 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 네임 스페이스에는 여러 가지식이 있으며 자신 만의 식을 만들 수 있습니다. 디자인이나 컴파일 타임에 알고리즘이 무엇인지 정확히 모르는 경우 이것이 유용 할 수 있다고 생각합니다. 과학 계산기를 작성하기 위해 이것을 사용하는 어딘가의 예를 보았습니다. 베이지안 시스템이나 유전자 프로그래밍 에도 사용할 수 있습니다(일체 포함). 내 경력에서 몇 번이나 Excel과 비슷한 기능을 작성하여 사용 가능한 데이터를 조작 할 수있는 간단한 표현 (추가, 서브 트리 등)을 입력 할 수있었습니다. .Net 3.5 이전에는 C # 외부의 일부 스크립팅 언어에 의존했거나 즉시 코드 생성 기능을 사용하여 .Net 코드를 즉시 작성해야했습니다. 이제 표현 트리를 사용하겠습니다.


답변

특정 장소에서 한 번만 사용되는 메소드를 사용하는 장소에서 멀리 떨어져 정의하지 않아도됩니다. 정렬과 같은 일반적인 알고리즘의 비교기로 사용하면 정렬을 호출하기 위해 다른 곳을 보도록 강요하지 않고 정렬을 호출하는 사용자 정의 정렬 함수를 정의 할 수 있습니다.

그리고 그것은 실제로 혁신이 아닙니다. LISP는 약 30 년 이상 람다 기능을 가지고 있습니다.