[c#] .Net 4.0에서 Tuple을 사용할 수있는 실제 예?

.Net 4에 도입 된 Tuple을 보았지만 어디에 사용할 수 있는지 상상할 수 없습니다. 우리는 항상 Custom 클래스 또는 Struct를 만들 수 있습니다.



답변

그게 요점 입니다. 항상 사용자 정의 클래스 나 구조체를 만들지 않는 것이 더 편리 합니다. 이 같은 개선 Action또는 Func…이 유형을 직접 만들 수 있지만 그들이 프레임 워크에 존재하는 것이 편리합니다.


답변

튜플을 사용하면 2 차원 사전 (또는 해당 문제에 대한 n 차원)을 쉽게 구현할 수 있습니다. 예를 들어, 이러한 사전을 사용하여 통화 교환 매핑을 구현할 수 있습니다.

var forex = new Dictionary<Tuple<string, string>, decimal>();
forex.Add(Tuple.Create("USD", "EUR"), 0.74850m); // 1 USD = 0.74850 EUR
forex.Add(Tuple.Create("USD", "GBP"), 0.64128m);
forex.Add(Tuple.Create("EUR", "USD"), 1.33635m);
forex.Add(Tuple.Create("EUR", "GBP"), 0.85677m);
forex.Add(Tuple.Create("GBP", "USD"), 1.55938m);
forex.Add(Tuple.Create("GBP", "EUR"), 1.16717m);
forex.Add(Tuple.Create("USD", "USD"), 1.00000m);
forex.Add(Tuple.Create("EUR", "EUR"), 1.00000m);
forex.Add(Tuple.Create("GBP", "GBP"), 1.00000m);

decimal result;
result = 35.0m * forex[Tuple.Create("USD", "EUR")]; // USD 35.00 = EUR 26.20
result = 35.0m * forex[Tuple.Create("EUR", "GBP")]; // EUR 35.00 = GBP 29.99
result = 35.0m * forex[Tuple.Create("GBP", "USD")]; // GBP 35.00 = USD 54.58


답변

있다 우수한 기사는MSDN 매거진에는 BCL에 Tuple을 추가하는 데 따른 배타적 및 디자인 고려 사항에 대해 가 있습니다. 값 유형과 참조 유형 중에서 선택하는 것이 특히 흥미 롭습니다.

기사에서 분명하게 알 수 있듯이 Tuple의 원동력은 Microsoft 내부의 많은 그룹이 F # 팀을 사용하고 있다는 것입니다. 언급되지는 않았지만 C # (및 VB.NET)의 새로운 “dynamic”키워드도 이와 관련이 있다고 생각합니다. 튜플은 동적 언어에서 매우 일반적입니다.

그렇지 않으면 자신의 poco를 만드는 것보다 특히 우월하지 않습니다. 적어도 구성원에게 더 나은 이름을 줄 수 있습니다.


업데이트 : C # 버전 7의 큰 개정으로 인해 이제 훨씬 더 많은 구문 사랑을 받고 있습니다. 의 예비 발표이 블로그 게시물의 .


답변

다음은 작은 예입니다. 사용자 ID가 주어지면 사용자의 핸들과 이메일 주소를 조회해야하는 메소드가 있다고 가정 해 보겠습니다. 항상 해당 데이터를 포함하는 사용자 지정 클래스를 만들거나 해당 데이터에 대한 ref / out 매개 변수를 사용하거나 새 POCO를 만들지 않고도 Tuple을 반환하고 멋진 메서드 서명을 가질 수 있습니다.

public static void Main(string[] args)
{
    int userId = 0;
    Tuple<string, string> userData = GetUserData(userId);
}

public static Tuple<string, string> GetUserData(int userId)
{
    return new Tuple<string, string>("Hello", "World");
}


답변

Project Euler의 문제 11 을 해결하기 위해 튜플을 사용했습니다 .

class Grid
{
    public static int[,] Cells = { { 08, 02, 22, // whole grid omitted

    public static IEnumerable<Tuple<int, int, int, int>> ToList()
    {
        // code converts grid to enumeration every possible set of 4 per rules
        // code omitted
    }
}

이제 다음으로 전체 문제를 해결할 수 있습니다.

class Program
{
    static void Main(string[] args)
    {
        int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
        Console.WriteLine("Maximum product is {0}", product);
    }
}

내가 할 수 이것에 대한 사용자 지정 형식을 사용하고 있지만 보았다 것입니다 정확히 튜플처럼 .


답변

C #의 튜플 구문은 엄청나게 부피가 커서 튜플을 선언하기가 어렵습니다. 그리고 패턴 매칭이 없기 때문에 사용하기도 힘들다.

그러나 때로는 클래스를 생성하지 않고 객체의 임시 그룹화를 원합니다. 예를 들어 목록을 집계하고 싶지만 하나가 아닌 두 개의 값을 원한다고 가정 해 보겠습니다.

// sum and sum of squares at the same time
var x =
    Enumerable.Range(1, 100)
    .Aggregate((acc, x) => Tuple.Create(acc.Item1 + x, acc.Item2 + x * x));

값 모음을 단일 결과로 결합하는 대신 단일 결과를 값 모음으로 확장 해 보겠습니다. 이 함수를 작성하는 가장 쉬운 방법은 다음과 같습니다.

static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
    Tuple<T, State> res;
    while ((res = f(seed)) != null)
    {
        yield return res.Item1;
        seed = res.Item2;
    }
}

f일부 상태를 튜플로 변환합니다. 튜플에서 첫 번째 값을 반환하고 새 상태를 두 번째 값으로 설정합니다. 이를 통해 계산 내내 상태를 유지할 수 있습니다.

다음과 같이 사용합니다.

// return 0, 2, 3, 6, 8
var evens =
    Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
    .ToList();

// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var fibs =
    Unfold(Tuple.Create(0, 1), state => Tuple.Create(state.Item1, Tuple.Create(state.Item2, state.Item1 + state.Item2)))
    .Take(10).ToList();

evens상당히 간단하지만 fibs조금 더 영리합니다. 그는 state실제 (N-1) 각각의 FIB (N-2)와 FIB를 유지하는 튜플이다.


답변

나는 그들 자신을 설명하지 않는 코드를 생성하기 때문에 그것들의 남용을 좋아하지 않지만 그들은 IStructuralEquatable 및 IStructuralComparable을 구현하기 때문에 즉석 복합 키를 구현하는 것이 굉장합니다 (조회 및 ​​주문에 모두 사용 목적).

그리고 그들은 내부적으로 모든 항목의 해시 코드를 결합합니다. 예를 들어 다음은 Tuple의 GetHashCode (ILSpy에서 가져옴)입니다.

    int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
    {
        return Tuple.CombineHashCodes(comparer.GetHashCode(this.m_Item1), comparer.GetHashCode(this.m_Item2), comparer.GetHashCode(this.m_Item3));
    }