튜플이 해결하도록 설계된 요구 사항은 무엇입니까?


94

튜플의 새로운 C # 기능을보고 있습니다. 궁금합니다. 튜플이 해결하도록 설계된 문제는 무엇입니까?

앱에서 튜플을 무엇에 사용 했습니까?

최신 정보

지금까지 답변 해주셔서 감사합니다. 마음에 똑바로있는 것이 있는지 살펴 보겠습니다. 튜플의 좋은 예가 좌표로 지적되었습니다. 이게 맞나요?

var coords = Tuple.Create(geoLat,geoLong);

그런 다음 튜플을 다음과 같이 사용하십시오.

var myLatlng = new google.maps.LatLng("+ coords.Item1 + ", "+ coords.Item2 + ");

그 맞습니까?



4
글쎄, 난 ...이 개 답변 생각할 수
정오 실크

13
"좌표"의 개념이 클래스로서 의미가 있다면 클래스로 만들 것입니다. 유형 작성을 정당화하는 데이터 세트에 대해 합리적인 "비즈니스 논리"개념 이 없는 상황에서는 튜플을 사용하십시오 .
Eric Lippert

13
좌표는 튜플의 좋은 예가 아닙니다. C #의 튜플은 (함수에서) 두 값을 반환해야하는 경우 임시 솔루션입니다. 하나의 결과 유형과 하나의 출력 매개 변수를 설정하는 대신 하나의 튜플을 반환하는 것이 더 우아합니다. 이렇게하면 두 번째 매개 변수를 미리 선언 할 필요가 없습니다. 차이점은 C ++에서 훨씬 더 분명합니다 (결과를 구성 할 수는 있지만 out / ref 매개 변수는 구성 할 수 없습니다).
greenoldman

8
) 파이썬이 있었고, 때문에 파이썬은 C #이없는 것이 아무것도 가질 수 없다
에반 가자미

답변:


117

프로그램을 작성할 때 클래스를 만드는 것을 정당화하기에 충분한 공통성이없는 값 세트를 논리적으로 그룹화하는 것이 매우 일반적입니다.

많은 프로그래밍 언어를 사용하면 한 가지 방법으로 만 유형을 만들지 않고도 관련없는 값 집합을 논리적으로 그룹화 할 수 있습니다.

void M(int foo, string bar, double blah)

논리적으로 이것은 int, string, double의 3- 튜플 인 하나의 인수를 취하는 메소드 M과 정확히 동일합니다. 그러나 나는 당신이 실제로 만들지 않기를 바랍니다.

class MArguments
{
   public int Foo { get; private set; } 
   ... etc

MArguments가 비즈니스 로직에서 다른 의미를 가지지 않는 한.

"클래스보다 가벼운 일부 구조에서 관련이없는 데이터 묶음 그룹화"개념은 공식 매개 변수 목록뿐만 아니라 여러 곳에서 유용합니다. 메서드에 반환 할 두 가지 항목이 있거나 하나가 아닌 두 데이터로 사전에 키를 지정하려는 경우 등에 유용합니다.

튜플 형식을 지원하는 F #과 같은 언어는 기본적으로 사용자에게 상당한 유연성을 제공합니다. 매우 유용한 데이터 유형 집합입니다. BCL 팀은 F # 팀과 협력하여 모든 언어가 이점을 얻을 수 있도록 프레임 워크에 대해 하나의 튜플 유형을 표준화하기로 결정했습니다.

그러나 현재 C #에서는 튜플에 대한 언어 지원 이 없습니다 . 튜플은 다른 프레임 워크 클래스와 같은 또 다른 데이터 유형입니다. 그들에게는 특별한 것이 없습니다. 가상의 향후 버전 C #에서 튜플에 대한 더 나은 지원을 추가하는 것을 고려하고 있습니다. 보고 싶은 튜플과 관련된 기능에 대해 생각하는 사람이 있다면 디자인 팀에 전달해 드리겠습니다. 현실적인 시나리오는 이론적 인 생각보다 더 설득력이 있습니다.


1
@MalcomTucker : Asychrony와 병렬 처리는 언어 도구를 사용하여 실제 문제를 해결할 수있는 풍부한 영역으로 확실히 우리 마음에 있습니다. F # 스타일의 비동기 워크 플로가 반드시 C #에 가장 적합하다고 생각하지는 않지만 확실히 고무적입니다.
Eric Lippert 2010-06-22

60
튜플이 유용하지만 한 가지 큰 단점은 명확성입니다. 그것은을 의미한다 코드를 읽고 이해하기 어렵다 Item1, Item2튜플 이제까지 C #에서 언어 지원을 달성 할 경우, 등이 ..., 그들의 구성원이 코드를 허용 방식에 이름 (또는 적어도 별칭) 할 수 있도록 멋진 것을 그 용도 더 이해하기 쉽게합니다. 이러한 가상의 미래에서 나는 또한 적절한 "모양"의 튜플을 개별 매개 변수를 취하는 메서드에 대한 합법적 인 매개 변수로보고 싶습니다 (반대의 경우도 마찬가지). 그래서, Tuple<int,string,bool>에 전달 될 수 있습니다 M(int,string,bool). 메모 방법을 훨씬 쉽게 만들 것입니다.
LBushkin

2
이러한 "튜플"은 기본적으로 이름이 지정되지 않은 멤버가있는 모든 public액세스, 익명 struct 유형입니다 . 멤버 의 의미론에 대해 아무 것도 알려주지 않는 a를 처리하는 것보다 프로그래머 가 명명 된 멤버로 a 를 작성 하고 반환하도록하는 것이 좋습니다. structtuple
bobobobo

1
@ Hi-Angel :이 주장은 튜플으로 간주되는 것과 그렇지 않은 것에 대해 고민 하는 것이 아니라, 현대 LOB (기간 업무) 개발자가 생산성을 높이기 위해 사용할 수있는 기능 세트에 대한 것입니다 . LBushkin은 디자인 팀이 항상 듣는 기능 요청을 표현하고 있습니다. 즉, 몇 개의 필드를 모으기 위해 전체 클래스를 만드는 데 드는 수고와 비용없이 일종의 "레코드 유형"을 만들고자하는 욕구입니다. C #에는 이미 메서드에 대한이 기능이 있습니다. "매개 변수 목록"이라고합니다.
Eric Lippert

2
@ Hi-Angel : "이름으로 메소드 매개 변수에 액세스하려면 별도의 클래스를 만들어야합니다."라는 인수를 만들지 않을 것입니다. 이는 매우 무거워 보이지만 우리가 사용하는 데 익숙하기 때문에 무거워 보입니다. 메서드를 호출 할 때 임의의 유형 및 이름을 사용하여 임의의 변수 집합을 즉시 연결하는 기능 . 어떤 언어에도 그러한 기능이 없다고 상상해보십시오. 모든 메서드는 하나의 인수 만 사용할 수 있으며 두 개를 전달하려면 유형을 만들고 인스턴스를 전달해야합니다.
Eric Lippert

22

튜플은 컬렉션의 변경 불가능한 구현을 제공합니다.

튜플의 일반적인 사용을 제외하고 :

  • 클래스를 만들지 않고도 공통 값을 그룹화
  • 함수 / 메소드에서 여러 값을 반환하려면
  • 기타...

변경 불가능한 객체는 본질적으로 스레드로부터 안전합니다.

불변 개체는 다중 스레드 응용 프로그램에서 유용 할 수 있습니다. 여러 스레드는 다른 스레드에 의해 변경되는 데이터에 대한 걱정없이 불변 객체가 나타내는 데이터에 대해 작동 할 수 있습니다. 따라서 변경 불가능한 객체는 변경 가능한 객체보다 스레드 안전성이 더 높은 것으로 간주됩니다.

에서 "불변의 객체" 위키 피 디아에


질문에 추가 정보를 추가해 주셔서 감사합니다. 매우 감사.
Chaddeus

불변 컬렉션을 원한다면 Tuple이 아닌 불변 컬렉션을 사용해야합니다. 차이점은 대부분의 변경 불가능한 컬렉션의 경우 컴파일 타임에 요소 수를 지정할 필요가 없다는 것입니다
BlueRaja-Danny Pflughoeft 2014

@ BlueRaja-DannyPflughoeft이 ​​답변을 작성했을 때 C # 불변 컬렉션 클래스는 BCL에서 여전히 사용할 수 없었습니다. MS가 C #에서 튜플 구현을 중성화했기 때문에 '컬렉션'을 '객체'로 변경하겠습니다
Evan Plaice

12

그것은에 대한 대안을 제공 ref하거나 out당신이 방법이있는 경우의 요구는 응답의 일환으로 여러 새 개체를 반환 할 수있다.

또한 2 개 또는 3 개의 기존 유형을 매시업하고이 조합에 대해서만 클래스 / 구조체를 추가 할 필요가없는 경우 기본 제공 유형을 반환 유형으로 사용할 수 있습니다. (함수가 익명 유형을 반환 할 수 있기를 원하십니까? 이것은 그 상황에 대한 부분적인 대답입니다.)


제길. 좋은. 몇 년 전에 튜플이 무엇인지 확인했으면 좋겠습니다;).
sabiland



4

개인적으로 튜플은 조사주기에 있거나 단순히 "연주"할 때 개발의 반복적 인 부분이라는 것을 알게되었습니다. 튜플은 제네릭이기 때문에 제네릭 매개 변수로 작업 할 때 생각하는 경향이 있습니다. 특히 제네릭 코드를 개발하고 싶을 때 "이 호출을 어떻게하면 좋을까요?"라고 스스로에게 묻지 않고 코드 끝에서 시작합니다. 보려고? ".

나는 Tuple이 형성하는 컬렉션이 목록의 일부가되고 List>를 쳐다 보는 것이 실제로 목록의 의도 나 작동 방식을 표현하지 않는다는 것을 자주 깨닫습니다. 나는 종종 그것으로 "살고"있지만, 목록을 조작하고 값을 변경하고 싶다는 생각이 든다.이 시점에서 나는 그것을 위해 반드시 새로운 튜플을 만들고 싶지는 않다. 그래서 나는 내 자신의 클래스 나 구조체를 만들어야한다. 조작 코드를 추가 할 수 있습니다.

물론 확장 메서드는 항상 있습니다.하지만 추가 코드를 일반 구현으로 확장하고 싶지는 않습니다.

데이터를 튜플로 표현하고 싶은데 튜플을 사용할 수없는 경우가있었습니다. (VS2008)이 경우 저는 방금 Tuple 클래스를 만들었으며 스레드로부터 안전하게 만들지 않습니다 (불변).

그래서 나는 Tuples가 목적을 설명하는 유형 이름을 잃어 버리는 대신 게으른 프로그래밍이라고 생각합니다. 다른 비용은 매개 변수로 사용되는 튜플의 서명을 선언해야한다는 것입니다. 부풀어 보이기 시작하는 여러 메서드 후에는 메서드 서명을 정리할 때 클래스를 만드는 것이 가치가 있다고 느낄 수 있습니다.

저는 클래스를 이미 작업중인 클래스의 공용 멤버로 지정하는 것으로 시작하는 경향이 있습니다. 그러나 단순히 값 모음을 넘어서 확장되는 순간 자체 파일을 가져 와서 포함하는 클래스 밖으로 이동합니다.

그래서 돌이켜 보면 저는 수업을 시작하고 작성하고 싶지 않을 때 튜플을 사용한다고 믿습니다. 그리고 지금 제가 쓰고있는 것에 대해 생각하고 싶습니다. 즉, Tuple의 서명이 30 분 동안 텍스트에서 상당히 많이 변경 될 수 있으며이 메서드에 필요한 데이터가 무엇인지, 그리고 반환 할 값을 반환하는 방법을 파악할 수 있습니다.

코드를 리팩토링 할 기회가 생기면 종종 그 안에 튜플의 위치에 대해 질문을 할 것입니다.


3

2010 년 이후의 오래된 질문, 그리고 2017 년에는 닷넷이 변화하고 더 똑똑해졌습니다.

C # 7에서는 튜플에 대한 언어 지원을 도입하여 새롭고보다 효율적인 튜플 유형을 사용하여 튜플의 필드에 의미 체계 이름을 사용할 수 있습니다.

2017 및 .Net 4.7 (또는 Nuget 패키지 System.ValueTuple 설치) 대비 매우 효율적이고 간단한 방법으로 튜플을 생성 / 사용할 수 있습니다.

     var person = (Id:"123", Name:"john"); //create tuble with two items
     Console.WriteLine($"{person.Id} name:{person.Name}") //access its fields

메서드에서 둘 이상의 값 반환 :

    public (double sum, double average) ComputeSumAndAverage(List<double> list)
    {
       var sum= list.Sum();
        var average = sum/list.Count;
        return (sum, average);
    }

    How to use:

        var list=new List<double>{1,2,3};
        var result = ComputeSumAndAverage(list);
        Console.WriteLine($"Sum={result.sum} Average={result.average}");    

자세한 내용은 https://docs.microsoft.com/en-us/dotnet/csharp/tuples를 참조하십시오.


1

Tuple은 특정 유형을 만들고 싶지 않을 때 함수에서 여러 값을 반환하는 데 자주 사용됩니다. 파이썬에 익숙하다면 파이썬은 오랫동안 이것을 가지고 있습니다.


1

함수에서 둘 이상의 값을 반환합니다. getCoordinates ()는 x, y 또는 z를 반환하는 경우별로 유용하지 않지만 3 개의 int를 보유하는 전체 클래스와 객체를 만드는 것도 꽤 무거워 보입니다.


1

일반적인 용도는 2 개의 필드 만 포함하는 클래스 / 구조체를 생성하지 않고 대신 Tuple (또는 지금은 KeyValuePair)을 생성하는 것입니다. 반환 값으로 유용합니다. 매개 변수 N을 전달하지 마십시오.


0

C #에서 KeyValuePair가 새로 고침되어 Dictionary의 키 값 쌍을 반복합니다.


KeyValuePair특수 목적의 해결 방법으로 볼 수 있습니다. Python에서 반복하면 dict(키, 값) 튜플이 반환됩니다.
dan04

예, 파이썬처럼. :-) C #의 KeyValuePair가 튜플이 아니라는 것을 몰랐습니까?
Jubal

0

함수에서 값을 반환하는 동안 정말 유용합니다. 여러 값을 되돌릴 수 있으며 이는 일부 시나리오에서 상당히 절약됩니다.


0

나는 Tuples와 Key-Value 쌍 사이에서이 성능 벤치 마크를 우연히 발견했고 아마 흥미로울 것입니다. 요약하면 Tuple이 클래스이기 때문에 이점이 있다고 말합니다. 따라서 스택이 아닌 힙에 저장되며 인수로 전달 될 때 포인터가 유일하게 진행됩니다. 그러나 KeyValuePair는 구조체이므로 할당하는 것이 더 빠르지 만 사용할 때 느립니다.

http://www.dotnetperls.com/tuple-keyvaluepair

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.