La façon dont je le vois, un Tuple est un raccourci pour l'écriture d'un résultat de la classe (je
suis sûr qu'il ya d'autres utilisations).
Il existe en effet d'autres utilisations pour Tuple<>
- la plupart d'entre eux font abstraction de la sémantique d'un groupe de types qui partagent une structure similaire, et de les traiter simplement comme ensemble ordonné de valeurs. Dans tous les cas, une indemnité de n-uplets, c'est qu'ils évitez d'encombrer votre espace de noms avec des données, seules les classes qui exposer des propriétés, mais pas les méthodes.
Voici un exemple d'une utilisation raisonnable pour Tuple<>
:
var opponents = new Tuple<Player,Player>( playerBob, playerSam );
Dans l'exemple ci-dessus, nous voulons représenter une paire d'adversaires, un tuple est une façon pratique de l'appariement de ces instances sans avoir à créer une nouvelle classe. Voici un autre exemple:
var pokerHand = Tuple.Create( card1, card2, card3, card4, card5 );
Une main de poker peut être considéré simplement comme un ensemble de cartes - et n-uplet (peut être) un moyen raisonnable d'exprimer ce concept.
mettant de côté la possibilité que je
me manque le point de n-Uplets, est l'
exemple avec un n-uplet d'une mauvaise conception
choix?
De retour fortement typé Tuple<>
cas dans le cadre d'une API publique pour un type de public est rarement une bonne idée. Comme vous le reconnaître, les tuples, les parties impliquées (bibliothèque de l'auteur, à la bibliothèque de l'utilisateur) afin de convenir à l'avance de l'heure sur l'usage et l'interprétation du n-uplet types utilisés. Il est assez difficile de créer des Api qui sont intuitives et claires, à l'aide de Tuple<>
public ne peut que brouiller l'intention et le comportement de l'API.
Les types anonymes sont aussi une forme de tuple - cependant, ils sont fortement typés et vous permettent de spécifier claire, informative des noms pour les propriétés appartenant à ce type. Mais les types anonymes sont difficiles à utiliser sur les différentes méthodes qu'ils ont été principalement ajoutée pour soutenir les technologies comme LINQ où les projections serait de produire des types à qui nous n'aurions pas envie de leur attribuer un nom. (Oui, je sais que les types anonymes avec les mêmes types et propriétés nommées sont consolidés par le compilateur).
Ma règle d'or est: si vous retournez à partir de votre interface publique - faire d'un type nommé.
Mon autre règle de base pour l'utilisation de n-uplets est: nom des arguments de méthode et localc des variables de type Tuple<>
aussi clairement que possible - prendre le nom de représenter le sens des relations entre les éléments du tuple. Pense à ma var opponents = ...
exemple.
Voici un exemple de cas réels où je l'ai utilisé Tuple<>
pour éviter de déclarer des données de type uniquement pour une utilisation uniquement à l'intérieur de mon propre assemblée. La situation implique le fait que lors de l'utilisation de générique dictionnaires contenant des types anonymes, il devient difficile d'utiliser l' TryGetValue()
méthode pour rechercher des éléments dans le dictionnaire, parce que la méthode nécessite une out
paramètre qui ne peut pas être nommé:
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 );
}
}
}
P. S. Il y a une autre (plus simple) moyen de contourner les problèmes liés à des types anonymes dans les dictionnaires, et qui consiste à utiliser l' var
mot-clé pour permettre au compilateur de "déduire" le type pour vous. Voici la version:
var foundItem = peopleDict.FirstOrDefault().Value;
if( peopleDict.TryGetValue( "Smith", out foundItem ) )
{
// use foundItem...
}