11.4.7 웜플 튜플과 거대한 튜플
C# 팀이 친근한 표현으로 웜플(womple, 얼뜨기) 튜플이라고도 하는 단일 값을 가진 튜플(ValueTuple<T1>)은 기본적인 튜플 구문을 통해 자체적으로 생성할 수는 없지만 다른 튜플의 일부분은 될 수 있다. 앞서 살펴본 바와 같이, 제네릭 ValueTuple 구조체는 최대 여덟 개의 타입 매개변수를 가질 수 있다. 만약 C# 컴파일러가 여덟 개 이상의 요소를 가진 튜플 리터럴을 지원하려면 어떻게 해야 할까? 이 경우 애리티가 8인 ValueTuple<…>을 사용하고 일곱 개의 타입 인수에 대해서는 표현하려는 튜플 리터럴의 일곱 개 인수에 대응되도록 하되, 마지막 타입 인수를 중첩된 튜플 타입으로 선언한 후 나머지 요소를 이 중첩 튜플을 이용해서 나타내면 된다. 정확히 여덟 개의 int 요소를 가진 튜플 리터럴을 표현한다고 해보자. 이 경우 다음과 같이 코드를 작성할 수 있다.
ValueTuple<int, int, int, int, int, int, int, ValueTuple<int>>
웜플 튜플은 볼드로 나타냈다. 애리티가 8인 ValueTuple<…>은 이러한 용도로 사용하도록 특별히 설계되었다. 11.4.1절에서 설명한 바와 같이, 마지막 타입 인수(TRest)는 값 타입으로 제약 조건이 설정되어 있다. Item8 필드는 존재하지 않는 대신 Rest 필드가 존재한다.
혼돈스럽지 않도록 애리티가 8인 ValueTuple<…>의 마지막 요소는 튜플에 담을 값 자체가 아니라여러 값을 담은 튜플을 사용해야 한다는 점이 중요하다. 예를 들어 다음 튜플 타입을 보자.
ValueTuple<A, B, C, D, E, F, G, ValueTuple<H, I>>
이 튜플은 C# 문법으로는 애리티가 9인 (A, B, C, D, E, F, G, H, I) 타입 혹은 애리티가 8이고 마지막 타입이 튜플 타입인 (A, B, C, D, E, F, G, (H, I))로 사용될 수 있다.
개발자의 관점에서 보면 사실 이런 부분까지 세밀하게 걱정할 필요가 없다. 왜냐하면 여덟 개가 훨씬 넘는 요소를 가진 튜플에 대해서도 ItemX와 같은 이름으로 각각의 요소를 사용할 수 있도록 컴파일러 차원에서 지원하기 때문이다. 이는 개발자가 마지막 요소를 중첩된 ValueTuple로 명시적으로 지정하더라도 동일하다. 예를 들어 다음과 같이 다소 긴 튜플을 생각해 보자.
var tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
Console.WriteLine(tuple.Item16);
이 코드는 완벽히 유효한 코드다. 하지만 tuple.Item16이라는 표현식은 컴파일러가 tuple.Rest.Rest.Item2로 변환한다. 정확한 필드 이름을 사용하고 있다면 이처럼 사용해도 되지만 썩 권하고 싶은 방법은 아니다. 거대한 튜플에 대해서 알아봤으니 이제 그 반대의 경우도 살펴보자.