10분 이내에 마스터하는 C#에서의 튜플 소개
[[academy-video-youtube({"vid": "QC6hpl2iU0c", "start_time": "0", "title": "10분 이내에 C#의 튜플 소개", "creator": "Tim Corey", "length": "9m 49s"})]]
C# 메서드는 단일 반환 값을 중심으로 설계되어 있습니다, 이는 여러 반환이 진정으로 필요하지 않을 때까지 작동합니다. 주소 유효성 검사는 전형적인 예입니다: 입력이 유효한지 여부를 알고 싶고, 만약 그렇다면 복원된 표준 형식을 되돌려 받고 싶습니다. 이 쌍을 새 클래스로 감싸는 것은 하나의 메서드에 비해 무거워 보이며, out 매개변수는 입력과 출력을 혼합하여 나중에 관리하기 어렵게 됩니다. 이러한 상황에 대해 더 깔끔한 답을 제공하기 위해 언어에 튜플이 추가되었습니다.
그의 비디오 "10분 이내에 배우는 C# 튜플 소개"에서 Tim Corey는 포맷된 문자열과 유효성 플래그를 반환해야 하는 작은 주소 검증 메서드를 구축하면서 튜플을 설명합니다. 그는 튜플을 반환하는 문법, 멤버의 이름이 중요한 이유, 호출 시점에서 결과를 별도의 변수로 분리하는 방법, 신경 쓰지 않는 부분은 discard 문자를 사용하여 건너뛰는 방법을 다룹니다. 일회성 결과 클래스나 out 매개변수를 여전히 사용하는 독자들은 여기서 더 가벼운 패턴을 찾을 것입니다.
문제: 하나 이상의 값을 반환하기
[0:18 - 2:50] Tim은 거리 주소 문자열을 받는 ValidateAddress 메서드로 시작합니다. 그가 원하는 동작은 간단합니다: 입력이 "123 Sesame St"와 일치할 경우, 올바르게 포맷된 "123 Sesame Street"를 반환합니다; 그렇지 않으면, 주소가 유효하지 않음을 알립니다. 정리된 문자열과 성공 플래그, 두 가지 정보가 단일 호출에서 반환되어야 합니다.
튜플 이전의 옵션들은 모두 어색했습니다. ValidateAddressResult 클래스를 생성하는 것은 작동하지만, 다른 코드가 인스턴스를 생성하지 않을 일회용 유형을 프로젝트에 남깁니다. 포맷된 주소를 매개변수 목록을 통해 다시 전송하기 위해 out 매개변수를 사용하는 것도 가능하지만, 이는 메서드 서명에서 입력과 출력을 혼합하게 되어 호출 위치를 읽기 어렵게 만듭니다. 튜플은 이러한 경우를 처리하기 위해 도입되었습니다.
이름 없는 튜플 반환
[2:50 - 4:01] 튜플 반환형의 최소 구문은 둘 다 괄호 안에 타입을 감쌉니다:
public (string, bool) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}public (string, bool) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}이제 메서드는 (string, bool) 쌍을 반환합니다. 어떤 것이 이를 사용하려고 할 때 단점이 즉시 드러납니다. 멤버들에게 이름이 지정되지 않으면, IntelliSense는 이를 Item1와 Item2로 노출하며, 이를 통해 다음 독자는 각 값이 무엇을 나타내는지 알 수 없습니다. Tim은 구문이 가장 짧음에도 불구하고 이름 없는 튜플을 발송하지 않는 이유로 이를 지적합니다. result.Item2를 6개월 후에 읽는 비용이 한 번 이름을 입력하는 비용보다 높습니다.
튜플 구성원 이름 지정
[4:01 - 6:30] 튜플의 각 구성원에게 이름을 매기면 반환형 선언에 단일 줄 변경이 필요합니다:
public (string Address, bool IsValid) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}public (string Address, bool IsValid) ValidateAddress(string address)
{
if (address == "123 Sesame St")
{
return ("123 Sesame Street", true);
}
return (address, false);
}이제 호출 사이트가 자연스럽게 읽힙니다:
var result = ValidateAddress("123 Sesame St");
if (result.IsValid)
{
Console.WriteLine($"Your validated address is {result.Address}");
}
else
{
Console.WriteLine("That is an invalid address");
}var result = ValidateAddress("123 Sesame St");
if (result.IsValid)
{
Console.WriteLine($"Your validated address is {result.Address}");
}
else
{
Console.WriteLine("That is an invalid address");
}"123 Sesame St"로 코드를 실행하면 정식 형식이 출력됩니다. 앞의 1을 빼서 "23 Sesame St"를 만들면 IsValid가 거짓으로 반환되고 잘못된 주소 메시지를 출력합니다. 이제 메서드의 계약은 지원 클래스 파일이 필요 없는 이름이 있는 튜플로 호출 사이트에서 자체 문서화가 됩니다.
튜플은 두 개 이상의 구성원을 가질 수 있습니다. 세 개, 네 개, 다섯 개도 같은 방식으로 동작합니다. Tim은 튜플이 세 개 또는 네 개의 구성원을 초과할 때 보통 레코드나 클래스가 더 명확한 선택이 되지만, 단일 메서드에서 두세 개의 관련 값을 갖는 경우에는 튜플이 더 가벼운 선택으로 남는다고 언급합니다.
튜플을 개별 변수로 해체하기
[6:30 - 7:39] 때때로 호출자는 결과의 각 부분을 자체 변수에 보유하기를 원하며, 이는 단일 result에 접근하는 대신입니다. C#은 해체 구문으로 직접 지원합니다:
(string message, bool valid) = ValidateAddress("123 Sesame St");
if (valid)
{
Console.WriteLine($"Your validated address is {message}");
}(string message, bool valid) = ValidateAddress("123 Sesame St");
if (valid)
{
Console.WriteLine($"Your validated address is {message}");
}왼쪽의 변수 이름은 메서드의 튜플 구성원 이름과 일치할 필요가 없습니다. 여기에서 message가 Address을 대체하고 valid가 IsValid을 대체합니다. Tim은 이것이 해체자이지 소멸자가 아님을 지적합니다; 두 단어는 비슷하게 들리지만 완전히 다른 개념을 나타냅니다. 해체자는 튜플을 호출자가 실제로 원하는 로컬 변수로 쪼갭니다.
폐기 문자로 값 건너뛰기
[7:41 - 8:54] 호출자가 반환된 값의 일부만 필요로 할 때, 버리기 문자(_)는 필요 없는 부분을 삭제합니다:
(string message, _) = ValidateAddress("123 Sesame St");
Console.WriteLine(message);(string message, _) = ValidateAddress("123 Sesame St");
Console.WriteLine(message);밑줄은 컴파일러에게 "이 값을 의도적으로 무시합니다"를 의미합니다. 이는 unwanted라는 이름의 버리는 변수에 할당하는 것보다 명확합니다. 라인을 읽는 사람은 IsValid를 무시하는 것이 이 호출 사이트에서 고의적인 선택임을 알 수 있습니다.
마무리: 튜플이 필요한 때
[8:54 - 9:28] 튜플의 주요 사용 사례는 단일 반환을 위해 존재하는 클래스를 생성하지 않고 메서드에서 여러 값을 반환하는 겁니다. 메서드 서명에서 구성원 병명, 호출 사이트에서 그것들을 해체, 그리고 호출자가 필요하지 않은 것들을 버리는 것 이 세 가지 패턴이 튜플을 사용하는 데 편안함을 줍니다. 그것 이외에도 튜플은 익명 타입보다 읽기 쉬운 빠른 쌍 값을 활용하는 LINQ 투영과 중간 계산에 유용합니다.
결론
[9:28 - 9:49] 튜플은 C#이 메서드에서 한 번에 여러 값을 반환할 수 있는 간결한 방법을 제공합니다. 이름 있는 형식은 result.Address가 읽히고 result.Item1는 읽히지 않기 때문에 일상적으로 사용할 가치가 있는 버전입니다. 해체는 호출자가 그 형태를 선호할 때에 부품을 다시 로컬 변수로 승격시키고, 폐기 문자는 단일 호출이 필요한 것만 취하도록 합니다.
예제 팁: 동일한 튜플 형태를 세 곳 이상에서 해체하기 시작할 때, 이는 레코드로 졸업해야 한다는 신호입니다. 튜플은 모양이 하나의 메서드에 국한되어 있을 때 빛납니다; 모양이 도메인의 일부가 되는 즉시, 이름이 있는 타입은 스스로 비용을 감당합니다.
전체 동영상을 그의 YouTube 채널에서 보시고, 10-Minute Training 시리즈에서 모던한, 표현력 있는 C#을 작성하는 방법에 관한 자세한 통찰을 얻으세요.

