포스트

C# Tuple

C# Tuple

Tuple


여러 개의 개별 값을 이용하여 단일의 복합 값을 나타내는 데이터 구조.

각각의 값이 서로 연관되어 있음에도 새로운 타입을 작성하고 싶지 않다면,
추가적인 캡슐화 작업 없이 간단히 복합 구성을 사용할 수 있다.

🫧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
(int, int) t = (0, 1);
// t.ToString();
// Output: (0, 1)

// t.GetHashCode();

(double, int) t = (4.5, 3);
// t.Item1, t.Item2

(double Sum, int) t = (4.5, 3);
// t.Sum(=Item1), t.Item2

(double Sum, int Count) t = (4.5, 3);
// t.Sum(=Item1), t.Count(=Item2)

var t = (4.5, 3);
// t.Item1, t.Item2

var t = (Sum: 4.5, 3);
// t.Sum(=Item1), t.Item2

var t = (Sum: 4.5, Count: 3);  
// t.Sum(=Item1), t.Count(=Item2)

(double Sum, int Count) t = (Sum: 4.5, Count: 3);
// t.Sum, t.Count
// CS8123: 튜플 요소 이름 'Sum'은(는) 대상 형식 '(double Sum, int Count)'에서 다른 이름이 지정되었거나 이름이 지정되지 않았기 때문에 무시됩니다.

var sum = 4.5;
var count = 3;
var t = (sum, count);
Console.WriteLine($"Sum of {t.count} elements is {t.sum}.");
// Tuple Projection Initializer  
// Can't Projection: Tuple's Member Name(ToString, Rest, Item1, Item2...), Already Used

var t = 
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26);
// t.Item1 ~ t.Item26

컴파일 시간에 필드 이름을 기본 이름으로 변경
= 명시적 지정, 유추된 필드 이름 런타임 사용 불가능

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var xs = new[] { 4, 7, 9 };
var limits = FindMinMax(xs);
Console.WriteLine($"Limits of [{string.Join(" ", xs)}] are {limits.min} and {limits.max}");
// Output:
// Limits of [4 7 9] are 4 and 9

var ys = new[] { -9, 0, 67, 100 };
var (minimum, maximum) = FindMinMax(ys);
Console.WriteLine($"Limits of [{string.Join(" ", ys)}] are {minimum} and {maximum}");
// Output:
// Limits of [-9 0 67 100] are -9 and 100

(int min, int max) FindMinMax(int[] input)
{
    if (input is null || input.Length == 0)
    {
        throw new ArgumentException("Cannot find minimum and maximum of a null or empty array.");
    }

    var min = int.MaxValue;
    var max = int.MinValue;
    foreach (var i in input)
    {
        if (i < min)
        {
            min = i;
        }
        if (i > max)
        {
            max = i;
        }
    }
    return (min, max);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 할당 및 분해

// 두 튜플 형식의 요소 수가 동일함
// AND
// 각 튜플 위치에서 오른쪽 튜플 요소의 형식이 해당하는 왼쪽 튜플 요소의 형식과 동일하거나 해당 형식으로 암시적으로 변환 가능함

(int, double) t1 = (17, 3.14);
(double First, double Second) t2 = (0.0, 1.0);
t2 = t1;
// t2.First, t2.Second

(double A, double B) t3 = (2.0, 3.0);
t3 = t2;
// t3.A, t3.B

// 필드 이름은 무시되고 할당되지 않음
// t3.First, t3.Second

// = 대입 연산자를 이용한 튜플 인스턴스 개별 변수 분해

// 명시적 선언
var t = ("post office", 3.6);
(string destination, double distance) = t;
(string destination, var distance) = t;

// 괄호밖 var (형식화된 변수를 암시적 선언, 컴파일러가 유추)
var t = ("post office", 3.6);
var (destination, distance) = t;

// 기존 변수 사용
var destination = string.Empty;
var distance = 0.0;
var t = ("post office", 3.6);
(destination, distance) = t;

// 혼합  

// 삭제 (무시)
var (_, _, _, a, _, b) = ~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 튜플 비교  

Console.WriteLine((Display(1), Display(2)) == (Display(3), Display(4)));

int Display(int s)
{
    Console.WriteLine(s);
    return s;
}
// Output:
// 1
// 2
// 3
// 4
// False

// == 및 != 연산자는 단락(short-circuiting) 방식으로 튜플을 비교합니다. 즉, 같지 않은 요소 쌍을 충족하거나 튜플의 끝에 도달하는 즉시 연산이 중지됩니다. 그러나 다음 예제와 같이 비교하기 전에 ‘모든’ 튜플 요소가 평가됩니다.

1
2
3
4
5
6
7
8
// Deconstruct  

var p = new Person("John", "Quincy", "Adams", "Boston", "MA");

// Deconstruct the person object.
var (fName, lName, city, state) = p;
var (temp, _, _) = p;

메모


이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.