더북(TheBook)

11.3.5 상속 시 튜플의 요소 이름 확인

튜플의 변환 과정에서 튜플 요소의 이름이 크게 중요한 역할을 하지 않음에도 불구하고, 상속 시에는 튜플 요소 이름에 대해 상당히 까다로운 제약이 있다. 튜플 타입을 매개변수로 받는 메서드가 있다고 가정해 보자. 만약 이 메서드가 베이스 클래스의 메서드를 재정의하거나 인터페이스를 구현했다면 튜플 요소에 명명한 이름까지도 완벽히 일치해야 한다.

예를 들어 다음과 같이 정의한 ISample 인터페이스가 있고, 그 내부의 ISample.Method를 구현해야 한다고 해보자(다음 예제의 각 행은 서로 다른 클래스에서 해당 메서드를 구현한 예로 생각해주기 바란다).

interface ISample
{
    void Method((int x, string) tuple);
}

public void Method((string x, object) tuple) {}  ----- 튜플 요소의 타입이 틀림
public void Method((int, string) tuple) {}  ----- 첫 번째 튜플 요소의 이름이 누락됨
public void Method((int x, string extra) tuple) {} ----- 두 번째 튜플 요소가 이름을 가짐(인터페이스에서는 이름을 명명하지 않았음)
public void Method((int wrong, string) tuple) {}  ----- 첫 번째 튜플 요소의 이름이 일치하지 않음
public void Method((int x, string, int) tuple) {}  ----- 튜플 타입의 애리티가 다름
public void Method((int x, string) tuple) {}  ----- 유효함

이 예제에서는 인터페이스를 구현하는 경우만 다루었지만 베이스 클래스의 멤버를 재정의할 때도 동일한 제약이 따른다. 그리고 예제에서는 튜플 타입을 매개변수로만 사용했지만 반환 타입으로 튜플을 사용해도 마찬가지다. 이런 이유로 인터페이스나 virtual/abstract 클래스 내에서 정의하는 메서드가 사용하는 튜플 요소의 이름을 변경하면 브레이킹 체인지(breaking change)를 유발한다. 공개 API에서 이런 작업을 해야 한다면 다시 한 번 주의해야 한다!

Note ≡


메서드를 재정의하거나 인터페이스를 구현할 때 매개변수의 이름이 변경되더라도 컴파일러가 이를 문제 삼지 않는 점을 생각하면, 튜플 요소의 이름으로 인해 문제가 발생하는 부분은 다소 일관성이 없는 것처럼 느껴질 수도 있다. 인터페이스를 구현할 때 매개변수의 이름을 달리했다면, 인수의 이름을 지정하는 방식으로 메서드를 호출할 때 인터페이스를 참조하는지 아니면 실제 구현체를 참조하는지에 따라 문제가 발생할 가능성이 있다. C#을 처음부터 다시 설계한다면 몰라도 지금으로서는 어쩔 도리가 없다.

C# 7.3에는 튜플을 비교할 수 있는 ==!= 연산자가 포함되었다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.