Home Full Site
C# 10 : 향상된 람다식 유추

기존의 C# 버전에서는 람다식(혹은 메서드 그룹)을 변수에 할당할 때, Delegate 타입을 명시적으로 지정해 주어야 했다. 예를 들어, 아래 예제 (1)에서 C# 9은 항상 Func Delegate를 명시적으로 표시해야 했는데, C# 10에서는 (2)에서 처럼 var 를 사용하여 컴파일러가 Delegate 타입을 유추하도록 할 수 있다.

물론 컴파일러가 모든 경우에 유추할 수 있는 것은 아닌데, 파라미터 타입 정보 등이 부족한 경우에는 유추할 수 없게 되어 컴파일 에러를 낼 수도 있다.


예제

// (1) C# 9: 문자열 s를 입력받아 정수를 리턴함
Func<string, int> s2i = (string s) => int.Parse(s);
int i = s2i("101");

// (2) C# 10: 명시적 Func 대신 var를 사용할 수 있음
var s2i = (string s) => int.Parse(s);



C# 10 : 람다식 리턴 타입 유추

람다식의 리턴값이 애매한 경우, 컴파일러는 타입 유추를 못할 수가 있는데, C# 10에서 이를 향상하기 위해 람다식 앞에 리턴타입을 지정하는 기능을 제공하고 있다. 아래 예제에서, (1)에서는 리턴 타입이 ArgumentException 타입인지 InvalidCastException 타입인지 판단할 수 없어 에러를 발생시키지만, (2)에서는 람다식 앞에 리턴 타입이 Exception 타입임을 명시하여 컴파일러가 bool 입력과 Exception 리턴을 유추할 수 있게 된다.

예제

// (1) 에러: (CS8917) The delegate type could not be inferred.
var ex = (bool b) => b ? new ArgumentException() : new InvalidCastException();

// (2) Fix: 리턴타입을 앞에 명시
var ex = Exception (bool b) => b ? new ArgumentException() : new InvalidCastException();



C# 10 : 람다식 Attribute

지금까지 Attribute (특성)은 메서드(method) 혹은 로컬함수(local function)에서만 사용되었는데, C# 10에서는 람다식에도 Attribute를 사용할 수 있다. 하지만, 람다는 메서드(혹은 로컬함수)와는 다르게 호출되기 때문에, Attribute가 람다식 내에서 사용되지는 못하고, 다만 코드분석(Code Analysis) 혹은 Reflection 등에서만 활용될 수 있다.

예제

// 람다식 Attribute 지정하기
var s2i = [MySample(1)] (string s) => int.Parse(s);
int i = s2i("111");
Console.WriteLine(i);


public class MySample : Attribute
{
    private int _id;
    public MySample(int id)
    {
        _id = id;
    }
}



C# 10 : Method group 타입 유추

위의 람다식에서와 같이, C# 10은 메서드 그룹에서 Delegate 타입을 유추하는 기능을 제공한다. 메서드 그룹(method group)이란 통상 메서드명을 가리키는 것으로, 하나의 메서드는 서로 다른 수와 타입의 메서드 오버로드(overrode)들을 가질 수 있으므로, 이를 메서드 그룹이라 부른다. 예를 들어, Add 메서드 그룹에는 Add(int), Add(int, int) 등과 같이 하나 이상의 여러 메서드 오버로드들을 가질 수 있으며, 이때 Add를 메서드 그룹이라 한다.

일반적으로 메서드 그룹으로부터 Delegate 타입을 얻어내어 사용할 수 있는데, C# 10에서는 이때 명시적인 Delegate 대신 var 를 사용하여 컴파일러가 그 타입을 유추할 수 있는 기능을 제공하고 있다.

아래 예제에서 Console.Read 메서드는 메서드 원형이 int Console.Read() 으로서 입력파라미터가 없고 int를 리턴하는 메서드이다. 한가지 주의할 점은 Read 메서드를 메서드명만 사용해야 하는데 Read()와 같이 괄호를 치면 실제 Read 메서드를 호출하여 int를 리턴하므로 readOne 타입이 Func가 아닌 int가 된다는 점이다.

컴파일러가 메서드 그룹으로부터 타입을 유추할 때, 만약 그 메서드가 여러 개의 메서드 오버로드들을 가지고 있다면, 정확한 타입을 유추할 수 없기 때문에, 에러가 발생한다.


예제

// Read 메서드 그룹으로부터 Func<int> 타입 유추.
// Console.Read() 메서드는 입력 파라미터가 없고, int를 리턴함.
var readOne = Console.Read;

int c1 = readOne();
int c2 = readOne();
Console.WriteLine($"{c1},{c2}");



© csharpstudy.com