Home 17. Tuple
Post
Cancel

17. Tuple

Intro

  • “exchange two variables without temp C#”
    을 검색 중 찾게된게 있는데1
    그 답이 Tuple쓰면 된다하길래
    보다가 남겨봄.

Tuple types

  • C# 7.0 부터 간단한 데이터 구조에서
    여러 데이터 요소를 그룹화 하기위해 사용
  • 튜플 유형은 값 유형 이고
    튜플 요소는 공개 필드임
    이는 튜플을 가변값 유형으로 만듭니다.
  • .NET Framework 4.7 이상에서 사용가능하고
    .NET Framework 4.6.2 이하는
    NuGet 패키지 System.ValueTuple를 추가.

Example

  • 기본적으로 이래됨
    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
    
    Tuple<int, string> t1 = new Tuple<int, string>(1, "test1");
    Console.WriteLine(t1);
    
    (int, string) t2 = (2, "test2");
    Console.WriteLine(t2);
    
    var t3 = (3, "test3");
    Console.WriteLine(t3);
    Console.WriteLine(t3.Item1);
    Console.WriteLine(t3.Item2);
    
    (int count, string name) t4 = (4, "test4");
    Console.WriteLine(t4);
    Console.WriteLine(t4.count);
    Console.WriteLine(t4.name);
    
    var t5 = (count:5, name:"test5");
    //var t5 = (count, name : 5, "test5");
    
    Console.WriteLine(t5);
    Console.WriteLine(t5.count);
    Console.WriteLine(t5.name);
    
    var t6 = Tuple.Create(6, "test6");
    Console.WriteLine(t6);
    
    var sum = 4.5;
    var count = 3;
    var t = (sum, count);
    Console.WriteLine($"Sum of {t.count} elements is {t.sum}.");
    // (1, test1)
    // (2, test2)
    // (3, test3)
    // 3
    // test3
    // (4, test4)
    // 4
    // test4
    // (5, test5)
    // 5
    // test5
    // (6, test6)
    
    • t1 처럼 쓰는 일은 거의 없어보임
      • 더 간단한게 많아보이는데뭐..
      • 또, 이 방법은
        element name을 명시 못하는것같음.
        내가 못찾았거나..
    • element name
      • 기본은 .Item?로 정해짐.
        ?는 element 순서
      • t3처럼 대충 하고 t3.Item?로 접근 가능
      • 이걸 t4처럼 명시적으로 이름도 지어줄 수 있음
        이걸 t5 처럼도 가능
      • 명시적으로 이름을 지어도 .Item? 는 여전히 가능
      • t 처럼 대충해도 변수 이름으로 유추해준다함.
      • 다만 Item?, ToString또는 Rest나
        중복이면 element이름으로 불가능
    • t6 처럼도 되는데 1~8개 element만 됨
    • 원래 튜플에 element 수에 대한 제한은 없음
  • 일반적으로
    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
    
    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);
    }
    
    • 이게 그래서 list로 return하는거랑 뭐다름? 했는데
      데이터형이 여러개여도 한번에 담을수 있고
      암튼 편한듯?
    • return을 여러개 쓰는 방법은 ref,out 등이 있었는데
      그런 방법들 보다 이게 더 간편하다함.

Tuple assignment and deconstruction

assignment

  • 튜플 간의 할당은 다음 조건을 모두 충족하는 경우 가능.
    • 두 튜플 모두 동일한 수의 요소를 가집니다.
    • 각 튜플 element에 대해
      오른쪽 튜플 요소의 유형은 해당 왼쪽 튜플 요소의 유형과
      동일하거나 암시적으로 변환 가능해야함.
  • 튜플 element 값은 순서에 따라 할당.
    이름은 무시되고 할당되지 않음.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    (int, double) t1 = (17, 3.14);
    (double First, double Second) t2 = (0.0, 1.0);
    t2 = t1;
    Console.WriteLine($"{nameof(t2)}: {t2.First} and {t2.Second}");
    // Output:
    // t2: 17 and 3.14
    
    (double A, double B) t3 = (2.0, 3.0);
    t3 = t2;
    Console.WriteLine($"{nameof(t3)}: {t3.A} and {t3.B}");
    // Output:
    // t3: 17 and 3.14
    

deconstruction

  • =(할당 연산자)을 사용해
    별도의 변수에서 튜플 인스턴스를 분해 할 수 있음.
    다음 방법 중 하나로 이를 수행할 수 있다.
    • 괄호 안에 각 변수의 유형을 명시적으로 선언.
      1
      2
      3
      4
      5
      6
      7
      
      var t = ("post office", 3.6);
      (string destination, double distance) = t;
      Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
      // Output:
      // Distance to post office is 3.6 kilometers.
      
      Console.WriteLine(destination);
      
    • 괄호 외부에 var 키워드를 사용해
      암시적으로 형식이 지정된 변수를 선언하고
      컴파일러가 해당 형식을 유추하게함.
      1
      2
      3
      4
      5
      
      var t = ("post office", 3.6);
      var (destination, distance) = t;
      Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
      // Output:
      // Distance to post office is 3.6 kilometers.
      
    • 기존 변수 사용
      1
      2
      3
      4
      5
      6
      7
      8
      
      var destination = string.Empty;
      var distance = 0.0;
      
      var t = ("post office", 3.6);
      (destination, distance) = t;
      Console.WriteLine($"Distance to {destination} is {distance} kilometers.");
      // Output:
      // Distance to post office is 3.6 kilometers.
      

Tuple equality

1
2
3
4
5
6
7
8
9
(int a, byte b) left = (5, 10);
(long a, int b) right = (5, 10);
Console.WriteLine(left == right);  // output: True
Console.WriteLine(left != right);  // output: False

var t1 = (A: 5, B: 10);
var t2 = (B: 5, A: 10);
Console.WriteLine(t1 == t2);  // output: True
Console.WriteLine(t1 != t2);  // output: False
  • element name은 신경 안씀.
  • C# 7.3부터 == 및 != 연산자 지원.
  • 비교가 가능한 조건은
    • 동일한 수의 element.
    • 각 element들은 비교 가능해야함.
      • 예를 들어, (1, (2, 3)) == ((1, 2), 3) 은
        1이 (1, 2)와 비교할 수 없기 때문에 컴파일되지 않음.
  • == 및 != 연산자는 튜플을 단락 방식으로 비교.
    즉, 같지 않은 한 쌍의 요소를 만나거나
    튜플의 끝에 도달하는 즉시 종료.
    그러나 비교하기 전에 다음 예제와 같이
    모든 튜플 요소가 평가됨.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    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
    
    
    • 비교때 문제가 생기면 바로 끝나는데
      그 전에 별개로 실행은 다 된다는것같음.

Tuples as out parameters

  • 일반적으로 out 매개 변수가 있는 메서드를
    튜플을 반환하는 메서드로 리팩터링함.
  • 그러나 out 매개변수가
    튜플 유형일 수 있는 경우가 있음.
  • 다음 예는 튜플을 out 매개변수로 사용하는 방법.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    var limitsLookup = new Dictionary<int, (int Min, int Max)>()
    {
        [2] = (4, 10),
        [4] = (10, 20),
        [6] = (0, 23)
    };
    
    if (limitsLookup.TryGetValue(4, out (int Min, int Max) limits))
    {
        Console.WriteLine($"Found limits: min is {limits.Min}, max is {limits.Max}");
    }
    // Output:
    // Found limits: min is 10, max is 20
    

Tuples vs System.Tuple

  • System.ValueTuple 형식으로 지원되는 C# 튜플은
    System.Tuple 형식으로 표시되는 튜플과 다름.
    주요 차이점은 다음과 같습니다.
    • System.ValueTuple 형식은 값 형식.
      System.Tuple 형식은 참조 형식.
    • System.ValueTuple 유형은 변경 가능.
      System.Tuple 형식은 변경할 수 없음.
    • System.ValueTuple 형식의 데이터 멤버는 필드.
      System.Tuple 형식의 데이터 멤버는 속성.

참고

This post is licensed under CC BY 4.0 by the author.

16. Callback

Intro 1

Comments powered by Disqus.