메타데이터 내의 튜플 요소 이름
이번 장에서 여러 번 살펴봤던 MinMax 메서드로 다시 돌아가 보자. LINQ to Object를 보강하기 위해 조합에 사용 가능한 public 메서드를 패키지화해서 노출한다고 해보자. 튜플 요소에 명명한 이름을 사용할 수 없다면 가독성이 상당히 나빠질 것이다. 그런데 CLR 수준에서는 반환값으로 튜플을 반환하면 튜플 요소의 이름을 유지하지 못한다고 하지 않았던가. 다행히 CLR은 out 매개변수와 매개변수의 기본값을 지정할 때 사용했던 메커니즘을 준용해서 CLR 차원에서 지원하지 않는 기능을 보강해 준다. 바로 특성을 이용하는 것이다!
이 경우 컴파일러는 TupleElementNamesAttribute라는 특성을 이용하여 해당 어셈블리 내에 튜플 요소의 이름을 인코딩해 둔다(유사한 성격의 다른 특성들과 마찬가지로 이 특성은 System.Runtime.CompilerServices 네임스페이스에 정의되어 있다). 예를 들어 public MinMax 메서드의 선언부를 C# 6로 나타내면 다음과 같다.
[return: TupleElementNames(new[] {"min", "max"})]
public static ValueTuple<int, int> MinMax(IEnumerable<int> numbers)
C# 7 컴파일러로 이 코드를 컴파일하면 튜플 문법을 직접 사용하라고 오류 메시지를 출력할 것이다. 하지만 이 코드를 C# 6로 컴파일하면 C# 7에서 튜플 요소에 이름을 부여한 것과 동일한 내용을 어셈블리에 추가해 준다.
중첩 타입을 사용하는 경우에는 이 특성이 다소 복잡하게 사용되지만, 특성에 직접 접근하여 그 내용을 해석해야 할 일은 거의 없을 것 같다. 단지 이처럼 특성을 이용하여 튜플이 지역 변수 수준을 벗어날 때 튜플 요소에 부여된 이름을 사용할 수 있도록 해준다는 사실을 아는 것만으로도 충분히 가치가 있다고 생각한다. 멤버가 private으로 선언된 경우에도 C# 컴파일러는 동일한 특성을 생성해 주는데, 사실 이 경우에는 이러한 특성이 없어도 올바르게 동작한다. 이는 접근 제한자를 고려하지 않고 멤버들을 동일한 방식으로 처리하도록 하여 논리를 단순하게 유지하기 위한 것으로 생각된다.