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이름으로 불가능
- 기본은 .Item?로 정해짐.
- t6 처럼도 되는데 1~8개 element만 됨
- 원래 튜플에 element 수에 대한 제한은 없음
- t1 처럼 쓰는 일은 거의 없어보임
- 일반적으로
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 등이 있었는데
그런 방법들 보다 이게 더 간편하다함.
- 이게 그래서 list로 return하는거랑 뭐다름? 했는데
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)) == ((1, 2), 3) 은
- == 및 != 연산자는 튜플을 단락 방식으로 비교.
즉, 같지 않은 한 쌍의 요소를 만나거나
튜플의 끝에 도달하는 즉시 종료.
그러나 비교하기 전에 다음 예제와 같이
모든 튜플 요소가 평가됨.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 형식의 데이터 멤버는 속성.
- System.ValueTuple 형식은 값 형식.
Comments powered by Disqus.