私の見たところ、タプルは結果クラスを書くための近道です(他の用途もあると思います)。
確かに他にも価値のある用途があります。Tuple<>
それらのほとんどは、類似した構造を共有する特定のタイプのグループのセマンティクスを抽象化し、それらを単に順序付けられた値のセットとして扱うことを含みます。すべての場合において、タプルの利点は、プロパティを公開するがメソッドは公開しないデータのみのクラスで名前空間を混乱させないことです。
の適切な使用例を次に示しますTuple<>
。
var opponents = new Tuple<Player,Player>( playerBob, playerSam );
上記の例では、対となる対を表現する必要があります。タプルは、新しいクラスを作成せずに、これらのインスタンスを対にする便利な方法です。次に別の例を示します。
var pokerHand = Tuple.Create( card1, card2, card3, card4, card5 );
ポーカーハンドは、単なるカードのセットと考えることができます-そしてタプル(多分)は、その概念を表現するための合理的な方法です。
タプルのポイントを逃している可能性を別にして、タプルの例は設計上の選択として不適切ですか?
強く型付けされたTuple<>
インスタンスをパブリック型のパブリックAPIの一部として返すことは、めったにありません。ご存じのように、タプルは、関係する当事者(ライブラリー作成者、ライブラリー・ユーザー)が、使用されるタプル・タイプの目的と解釈について事前に合意する必要があります。直感的で明確なAPIを作成することは十分に挑戦的であり、Tuple<>
公的に使用することはAPI の意図と動作を隠すだけです。
匿名型もタプルの一種ですが、匿名型は厳密に型指定されているため、型に属するプロパティに明確でわかりやすい名前を指定できます。しかし、匿名型はさまざまな方法で使用するのが困難です。これらは主に、射影によって通常は名前を割り当てたくない型を生成するLINQなどのテクノロジをサポートするために追加されました。(はい、同じ型と名前付きプロパティを持つ匿名型がコンパイラーによって統合されることを知っています)。
私の経験則は: あなたがあなたの公開インターフェースからそれを返すなら-それを名前付きの型にします。
タプルを使用するための他の経験則は、 名前メソッドの引数と型のlocalc変数をTuple<>
できるだけ明確にします-名前にタプルの要素間の関係の意味を表すようにします。私の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...
}