[C# 문법] 대리자 및 람다 식

참고


대리자(delegate) 란?

  • 대리자는 특정 매개 변수 목록 및 반환 형식이 있는 메서드에 대한 참조를 나타내는 형식을 정의합니다.
  • 매개 변수 목록과 반환 형식이 일치하는 메서드(정적 또는 인스턴스)를 해당 형식의 변수에 할당한 다음 직접 호출하거나 인수 자체로 다른 메서드에 전달한 다음 호출할 수 있습니다.
  • 다음 예제에서는 대리자 사용을 보여줍니다.
using System;
using System.Linq;

public class Program
{
    public delegate string Reverse(string s);

    static string ReverseString(string s)
    {
        return new string(s.Reverse().ToArray());
    }

    static void Main(string[] args)
    {
        Reverse rev = ReverseString;

        Console.WriteLine(rev("a string"));
    }
}
  • public delegate string Reverse(string s); 줄은 문자열 매개 변수를 사용한 다음 문자열 매개 변수를 반환하는 메서드의 대리자 형식을 만듭니다.
  • 정의된 대리자 형식과 정확히 동일한 매개 변수 목록 및 반환 형식을 포함하는 메서드는 static string ReverseString(string s) 대리자를 구현합니다.
  • Reverse rev = ReverseString; 줄에서는 해당 대리자 형식의 변수에 메서드를 할당할 수 있는 것이 표시됩니다.
  • Console.WriteLine(rev("a string")); 줄에서는 대리자 유형의 변수를 사용하여 대리자를 호출하는 방법을 설명합니다.

  • .NET에서는 개발 프로세스를 간소화 하기 위해 .NET 에는 프로그래머가 새 형식을 만들 필요 없이 다시 사용할 수 있는 대리자 형식 집합이 포함되어 있습니다.
  • 이러한 형식은 Func<>, Action<>, Predicate<> 이며 새로운 대리자 형식을 정의하지 않고도 이 형식을 사용할 수 있습니다.
  • 이 세 형식 사이에는 의도한 사용 방법과 관련하여 몇 가지 차이점이 있습니다.
    • Action<> 은 대리자의 인수를 사용하여 작업을 수행해야 할 때 사용됩니다. 캡슐화된 메서드가 값을 반환하지 않습니다.
    • Func<> 는 일반적으로 변환을 수행해야 할 때 사용됩니다. 즉, 대리자의 이수를 다른 결과로 변환해야 할 때 사용됩니다.
    • Predicate<> 는 인수가 대리자의 조건을 충족하는지 확인해야 할 때 사용됩니다. 이를 Func<T, bool> 로 작성할 수도 있습니다. 즉, 메서드가 부울 값을 반환한다는 의미입니다.
  • 이제 위의 예제를 가져와서 사용자 지정 형식 대신 Func<> 대리자를 사용하여 다시 작성할 수 있습니다.
using System;
using System.Linq;

public class Program
{
    static string ReverseString(string s)
    {
        return new string(s.Reverse().ToArray());
    }

    static void Main(string[] args)
    {
        Func<string, string> rev = ReverseString;

        Console.WriteLine(rev("a string"));
    }
}
  • 이 간단한 예제에서는 Main 메서드 외부에서 정의된 메서드를 사용하는 것이 불필요합니다.
  • 이럴 때는 익명 대리자 를 이용하여 보다 코드를 간단히 바꿀 수 있습니다.
  • 다음 예제 에서는 익명 대리자가 목록에서 짝수 번호만 필터링하고 콘솔에 출력합니다.
using System;
using System.Collections.Generic;

public class Program
{
    public static void Main(string[] args)
    {
        List<int> list = new List<int>();

        for (int i = 1; i <= 100; i++)
        {
            list.Add(i);
        }

        List<int> result = list.FindAll(
          delegate (int no)
          {
              return (no % 2 == 0);
          }
        );

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
  • 위와 같이 대리자 본문은 다른 모든 대리자와 마찬가지로 단순히 식 집합일 뿐입니다.
  • 그러나 별도의 정의가 아닌 메서드 호출에서 임시로 도입했습니다.
  • 이 방법의 경우에도 제거할 수 있는 많은 코드가 있습니다.
  • 이때 람다식을 사용하면 보다 코드를 줄일 수 있습니다.
using System;
using System.Collections.Generic;

public class Program
{
    public static void Main(string[] args)
    {
        List<int> list = new List<int>();

        for (int i = 1; i <= 100; i++)
        {
            list.Add(i);
        }

        List<int> result = list.FindAll(i => i % 2 == 0);

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }
}
  • 위의 예제에서 사용된 람다식은 i => i % 2 == 0 입니다.
  • 람다 식은 단지 대리자를 사용하는 데 더 편리한 구문입니다.
  • 내부적으로 수행되는 작업은 익명 대리자를 사용하는 경우와 비슷합니다.
  • 다시 말해, 람다는 단순히 대리자이므로 다음 코드 조각과 같이 문제 없이 이벤트 처리기로 사용할 수 있습니다.
public MainWindow()
{
    InitializeComponent();

    Loaded += (o, e) =>
    {
        this.Title = "Loaded";
    };
}
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY