내가 보는 방식으로 Tuple은 결과 클래스를 작성하는 지름길입니다 (다른 용도도 있음).
실제로 다른 귀중한 용도가 있습니다 Tuple<>
. 대부분 유사한 구조를 공유하는 특정 유형의 그룹의 의미를 추상화하고 단순히 일련의 값으로 취급합니다. 모든 경우에 튜플의 이점은 속성은 노출하지만 메서드는 노출하지 않는 데이터 전용 클래스로 네임 스페이스를 어지럽히 지 않는다는 것입니다.
다음은 합리적으로 사용되는 예입니다 Tuple<>
.
var opponents = new Tuple<Player,Player>( playerBob, playerSam );
위 예제에서 우리는 한 쌍의 상대를 나타내려고합니다. 튜플은 새 클래스를 만들지 않고도 이러한 인스턴스를 연결하는 편리한 방법입니다. 또 다른 예는 다음과 같습니다.
var pokerHand = Tuple.Create( card1, card2, card3, card4, card5 );
포커 패는 단순한 카드 세트로 생각할 수 있으며 튜플은 그 개념을 표현하는 합리적인 방법입니다.
Tuples의 요점을 놓칠 가능성을 제쳐두고 Tuple이있는 예는 나쁜 디자인 선택입니까?
Tuple<>
퍼블릭 타입의 퍼블릭 API의 일부로 강력한 타입의 인스턴스를 반환하는 것은 좋은 생각이 아닙니다. 본인이 알고 있듯이 튜플을 사용하려면 관련 당사자 (라이브러리 작성자, 라이브러리 사용자)가 사용중인 튜플 유형의 목적과 해석에 대해 미리 동의해야합니다. 직관적이고 명확한 API를 사용하여Tuple<>
공개적으로 API의 의도와 행동을 모호하게하는 것만으로 입니다.
익명 형식도 일종의 튜플 이지만 강력하게 형식이 지정되어 있으며 해당 형식에 속하는 속성에 대해 명확하고 유익한 이름을 지정할 수 있습니다. 그러나 익명 유형은 다른 방법으로 사용하기가 어렵습니다. 주로 LINQ와 같은 기술을 지원하기 위해 추가되었습니다. (예, 동일한 유형과 명명 된 속성을 가진 익명 유형이 컴파일러에 의해 통합되어 있음을 알고 있습니다).
내 경험 법칙은 공용 인터페이스에서 반환하는 경우 명명 된 유형으로 만드십시오 .
튜플을 사용하는 또 다른 경험의 규칙은 다음 과 같습니다. 이름 메서드 인수와 Tuple<>
가능한 유형의 localc 변수는 가능한 명확하게-이름이 튜플 요소 간의 관계의 의미를 나타내도록합니다. 내 var opponents = ...
예를 생각해보십시오 .
다음 은 내 어셈블리 내에서만 사용 Tuple<>
하기 위해 데이터 전용 유형 을 선언하지 않기 위해 사용한 실제 사례의 예입니다 . 익명 유형을 포함하는 일반 사전을 사용하는 경우 TryGetValue()
메소드에 out
이름을 지정할 수없는 매개 변수가 필요하기 때문에 메소드를 사용 하여 사전에서 항목을 찾는 것이 어려워지는 상황이 있습니다 .
public static class DictionaryExt
{
// helper method that allows compiler to provide type inference
// when attempting to locate optionally existent items in a dictionary
public static Tuple<TValue,bool> Find<TKey,TValue>(
this IDictionary<TKey,TValue> dict, TKey keyToFind )
{
TValue foundValue = default(TValue);
bool wasFound = dict.TryGetValue( keyToFind, out foundValue );
return Tuple.Create( foundValue, wasFound );
}
}
public class Program
{
public static void Main()
{
var people = new[] { new { LastName = "Smith", FirstName = "Joe" },
new { LastName = "Sanders", FirstName = "Bob" } };
var peopleDict = people.ToDictionary( d => d.LastName );
// ??? foundItem <= what type would you put here?
// peopleDict.TryGetValue( "Smith", out ??? );
// so instead, we use our Find() extension:
var result = peopleDict.Find( "Smith" );
if( result.First )
{
Console.WriteLine( result.Second );
}
}
}
PS 사전에서 익명 유형으로 인해 발생하는 문제를 해결하는 또 다른 (간단한) 방법이 있습니다. 즉, var
키워드를 사용 하여 컴파일러가 유형을 '유추'할 수 있습니다. 그 버전은 다음과 같습니다.
var foundItem = peopleDict.FirstOrDefault().Value;
if( peopleDict.TryGetValue( "Smith", out foundItem ) )
{
// use foundItem...
}