Quelle est la meilleure façon d'utiliser une paire (triple, etc) de valeurs comme une seule valeur en C#?

C'est, j'aimerais avoir un n-uplet de valeurs.

Le cas d'utilisation dans mon esprit:

Dictionary<Pair<string, int>, object>

ou

Dictionary<Triple<string, int, int>, object>

y a-t-il des types intégrés comme paire ou Triple? Ou Quelle est la meilleure façon de le mettre en œuvre?

mise à Jour Il y a quelques usage général tuples implémentations décrites dans les réponses, mais tuples sont utilisés comme clés dans les dictionnaires, vous devez additionaly vérifier le calcul correct du code de hachage. Un peu plus d'info sur cela dans un autre question .

Update 2 je suppose qu'il est également intéressant de rappeler, que lorsque vous utilisez une valeur comme une clé dans le dictionnaire, il devrait être immuable.

20
demandé sur Community 2008-09-19 17:31:14

16 réponses

j'ai implémenté une bibliothèque tuple en C#. Visite http://www.adventuresinsoftware.com/generics / et cliquez sur le lien" tuples".

6
répondu Michael L Perry 2008-09-19 13:38:26

Classes De Bâtiments

dans certains cas spécifiques, le framework .net fournit déjà des classes tuple-like que vous pourriez être en mesure d'exploiter.

couples et Triples

le générique du Système.Collection.Générique.KeyValuePair class pourrait être utilisé comme une implémentation de paire adhoc. C'est le de classe que l' Dictionnaire générique utilise en interne.

alternativement, vous pouvez être en mesure de faire avec le du Système.Collection.DictionaryEntry structure qui agit comme une paire rudimentaire et a l'avantage de disponible en mscorlib. Le côté négatif, cependant, est que cette structure n'est pas fortement typé.

Paires et Triples sont également disponibles sous la forme de la Système.Web.INTERFACE.Paire et du Système.Web.INTERFACE.Triplet classes. Même si ces classes vivent dans le système .Assemblage Web ils pourraient être parfaitement adaptés pour le développement de winforms. Toutefois, ces classes sont pas fortement tapé ni l'un ou l'autre et pourrait ne pas être approprié dans certains scénarios, comme un cadre général ou une bibliothèque.

ordre supérieur tuples

pour les tuples d'ordre supérieur, à moins de rouler votre propre classe, il peut ne soit pas une solution simple.

Si vous avez installé le F # language , vous pouvez faire référence au FSharp.Core.dll qui contient un ensemble de immuable Générique Microsoft.Fsharp.Core.Tuple classes jusqu'au sextuples Générique. Cependant, même si une non modifié FSharp.Code.dll peut être redistribué, F# est un langage de recherche et d'un travail en cours donc cette solution n'intéressera vraisemblablement que les milieux universitaires.

Si vous ne voulez pas créer votre propre classe et sont mal à l'aise en faisant référence à la bibliothèque F#, Une astuce pourrait consister à étendre la classe générique KeyValuePair de sorte que le membre de valeur soit lui-même un KeyValuePair imbriqué.

par exemple, le le code suivant illustre comment vous pouvez utiliser KeyValuePair afin de créer un triple:

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

Cela permet d'étendre la classe à n'importe quel niveau est requis.

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string> quadruple =
    new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>();
KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string> quintuple =
    new KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string>();

Rouler Propre

dans d'autres cas, vous pourriez avoir besoin de rouler votre propre classe tuple, et ce n'est pas difficile.

vous pouvez créer des structures simples comme ceci:

struct Pair<T, R>
{
    private T first_;
    private R second_;

    public T First
    {
        get { return first_; }
        set { first_ = value; }
    }

    public R Second
    {
        get { return second_; }
        set { second_ = value; }
    }
}

Frameworks et Bibliothèques

ce problème a déjà été abordé et les cadres d'usage général existent. Voici un lien vers un tel cadre:

20
répondu Maxime Labelle 2017-05-23 12:34:01
public struct Pair<T1, T2>
{
    public T1 First;
    public T2 Second;
}

public struct Triple<T1, T2, T3>
{
    public T1 First;
    public T2 Second;
    public T3 Third;
}
12
répondu Timothy Carter 2008-09-19 13:55:41

Fast-forward à 2010 .NET 4.0 prend désormais en charge n-tuples de l'arbitraire n . Ces tuples mettent en œuvre l'égalité structurelle et la comparaison comme prévu.

11
répondu Mauricio Scheffer 2010-08-15 00:49:31

paire et Triplet sont des classes existantes dans .net voir msdn:

Triplet

paire

je les ai récemment rencontrés, alors que je jouais avec viewstate decoding

9
répondu Adam Vigh 2008-09-19 13:35:18

d'habitude je crée juste ma propre structure, contenant les valeurs. C'est souvent un peu plus lisible ;)

3
répondu Grad van Horck 2008-09-19 13:33:45

KeyValuePair est la meilleure classe à étendre si vous ne voulez pas créer vos propres classes.

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

Vous pouvez l'étendre à autant de niveaux que vous le souhaitez.

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string> quadruple =
   new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string>();

Note : les classes Triplet et paire existent à l'intérieur du système .Web - dll, de sorte qu'il n'est pas très adapté pour d'autres solutions que ASP.NET.

2
répondu Seb Nilsson 2008-09-19 13:44:17

vous pouvez relativement facilement créer vos propres classes de tuple, la seule chose qui est potentiellement brouillon est votre égalité et les dérogations de hashcode (essentiel si vous allez les utiliser dans les dictionnaires).

il est à noter que la structure de .Net KeyValuePair<TKey,TValue> a égalité relativement lente et méthodes hashcode .

en supposant que ce n'est pas un souci pour vous, Il ya encore le problème que le code finit par être difficile à figure:

public Tuple<int, string, int> GetSomething() 
{
    //do stuff to get your multi-value return
}

//then call it:
var retVal = GetSomething();

//problem is what does this mean?
retVal.Item1 / retVal.Item3; 
//what are item 1 and 3?

dans la plupart de ces cas, je trouve plus facile de créer une classe d'enregistrement spécifique (au moins jusqu'à ce que C#4 fasse de ce compilateur-magic)

class CustomRetVal {
    int CurrentIndex { get; set; }
    string Message { get; set; }
    int CurrentTotal { get; set; }
}

var retVal = GetSomething();

//get % progress
retVal.CurrentIndex / retVal.CurrentTotal;
2
répondu Keith 2008-09-19 16:14:22

une solution simple n'a pas encore été mentionnée. Vous pouvez également utiliser un List<T> . Il est intégré, efficace et facile à utiliser. Accordé, il semble un peu bizarre au premier abord, mais il fait son boulot parfaitement, surtout pour un plus grand nombre d'éléments.

2
répondu mafu 2010-04-01 17:59:14

NGenerics - le populaire .Net algorithmes et structures de données de la bibliothèque, a récemment introduit immuable structures de données à l'ensemble.

les premières immuables à mettre en œuvre étaient les classes pair et tuple . Le code est bien rempli de tests et est très élégant. Vous pouvez le vérifier ici . Ils travaillent actuellement sur les autres alternatives immuables et ils devraient être prêts d'ici peu.

1
répondu husayt 2009-11-02 18:50:12

il n'y a pas d'ins construit, mais une classe est triviale à créer.

0
répondu Will 2008-09-19 13:34:45

Oui, il y a un système.Web.INTERFACE.La paire et le Système.Web.INTERFACE.Triplet (qui a un créateur surchargé pour le comportement de Type Pair!)

0
répondu ballpointpeon 2008-09-19 13:35:47

pour le premier cas, j'utilise habituellement

Dictionary<KeyValuePair<string, int>, object>
0
répondu Jonas Lincoln 2008-09-19 13:35:49

il n'y a pas de classes intégrées pour cela. Vous pouvez utiliser KeyValuePair ou déployer votre propre implémentation.

0
répondu aku 2008-09-19 13:35:55

vous pouvez utiliser le système.Collection.Générique.KeyValuePair que votre mise en œuvre de paire.

ou vous pouvez simplement mettre en œuvre votre propre, ils ne sont pas difficiles:

public class Triple<T, U, V>
{
  public T First {get;set;}
  public U Second {get;set;}
  public V Third {get;set;}
}

bien sûr, vous pourriez un jour avoir un problème qui Triple(string, int, int) n'est pas compatible avec Triple(int, int, string). Peut-être aller avec un Système.XML.Linq.XElement à la place.

0
répondu Amy B 2008-09-19 13:36:22

il y a aussi les types de Tuple dans F#; vous devez juste faire référence à FSharp.Core.DLL.

0
répondu TraumaPony 2008-09-19 13:42:58