11.4.3 튜플 변환 구현
여러 형태로 제공되는 ValueTuple 사이에는 어떠한 변환 기능도 제공하지 않으므로 CLR 수준에서는 ValueTuple 사이의 변환이 불가능하다. C#이 제공하는 변환 기능은 타입 정보로 표현할 수는 없지만, 컴파일러 차원에서 필요한 경우 새로운 타입을 생성하기도 하고 튜플의 각 요소별로 변환을 수행해 주기도 한다. 변환과 관련된 두 가지 예제를 살펴볼 텐데, 하나는 암시적 변환(int를 long으로 변환하는 암시적 변환)이고 다른 하나는 명시적 변환(int를 byte로 변환하는 명시적 변환)이다.
(int, string) t1 = (300, "text");
(long, string) t2 = t1;
(byte, string) t3 = ((byte, string)) t1;
컴파일러는 이 코드를 사용자가 다음과 같이 작성한 것처럼 생성한다.
var t1 = new ValueTuple<int, string>(300, "text");
var t2 = new ValueTuple<long, string>(t1.Item1, t1.Item2);
var t3 = new ValueTuple<byte, string>((byte) t1.Item1, t1.Item2));
이 예제는 앞서 살펴본 것처럼 튜플 타입 사이의 변환을 보여주지만, 튜플 리터럴을 튜플 타입으로 변환할 때도 동일한 작업이 수행된다. 그리고 튜플 내의 요소에 대해 타입 변환이 필요한 경우 항상 ValueTuple<…> 생성자가 사용된다.
지금까지 C# 컴파일러가 튜플 문법을 지원하기 위해 내부적으로 어떤 작업을 수행하는지 모두 살펴봤다. ValueTuple<…> 타입은 그 외에도 작업을 편리하게 수행할 수 있는 몇 가지 기능을 제공한다. 튜플의 범용성을 감안한다면 그리 많다고 할 수는 없지만 ToString() 메서드를 통해 튜플의 내용을 쉽게 살펴볼 수 있도록 출력 결과를 생성해 주고, 튜플을 비교할 수 있는 다양한 옵션을 제공하기도 한다. 그중 몇 가지 기능을 따로 살펴보자.