Pergunta

Isto é, eu gostaria de ter uma tupla de valores.

O caso de uso em minha mente:

Dictionary<Pair<string, int>, object>

ou

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

Há built-in tipos como par ou triplo? Ou qual é a melhor forma de implementar isso?

Atualizar Existem algumas implementações tuplas de uso geral descritos nas respostas, mas para tuplas utilizados como chaves nos dicionários você deve additionaly verificar cálculo correto do código de hash. Alguns mais informações sobre isso em outra pergunta href="https://stackoverflow.com/questions/102690/how-does-c-figure-out-the-hash-code-for-an-object"> .

Update 2 eu acho que também vale lembrar, que quando você usa algum valor como uma chave no dicionário, ela deve ser imutável.

Outras dicas

Classes Builtin

Em certos casos específicos, o .NET Framework já fornece tupla-like classes que você pode ser capaz de alavancagem.

pares e triplos

O genérico System.Collections.Generic.KeyValuePair classe pode ser usada como uma aplicação adhoc par. Esta é a classe que o genérico dicionário usa internamente.

Como alternativa, você pode ser capaz de se contentar com o System.Collections.DictionaryEntry estrutura que actua como um par rudimentar e tem a vantagem de estar disponível em mscorlib. No lado do baixo, no entanto, é que esta estrutura não é fortemente tipado.

pares e triplos também estão disponíveis na forma da System.Web.UI.Pair e System.Web.UI.Triplet classes. Mesmo que as classes teses viver no System.Web montagem que pode ser perfeitamente adequado para o desenvolvimento winforms. No entanto, essas classes são Não fortemente digitado, quer e pode não ser adequado em alguns cenários, como um quadro purposed geral ou biblioteca.

ordem superior tuplas

Para tuplas de ordem superior, curta de rolar sua própria classe, não pode não ser uma solução simples.

Se você tiver instalado o F # linguagem , você poderia fazer referência ao FSharp.Core.dll que contém um conjunto de imutável genérico Microsoft.Fsharp.Core.Tuple classes até sextuples genéricos. No entanto, mesmo que uma não modificada FSharp.Code.dll pode ser redistribuído, F # é uma linguagem de pesquisa e um trabalho em andamento de modo esta solução é provável que seja de interesse apenas nos círculos acadêmicos.

Se você não quiser criar sua própria classe e são desconfortáveis referenciando o # biblioteca F, um truque bacana poderia consistir em estender a classe KeyValuePair genérico de forma que o membro Valor é em si um KeyValuePair aninhada.

Por exemplo, o código a seguir ilustra como você pode alavancar o KeyValuePair, a fim de criar uma triplica:

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;

Isso permite estender a classe para qualquer nível arbitrário como é necessário.

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>();

rolar o seu próprio

Em outros casos, pode ser necessário recorrer a rolar seus próprios classe tupla, e isso não é difícil.

Você pode criar estruturas simples assim:

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 e bibliotecas

Este problema tem sido abordado antes e estruturas de uso geral existir. Abaixo está um link para um tal quadro:

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;
}

Fast-forward para 2010, .NET 4.0 agora suporta n-tuplas de arbitrária n . Estas tuplas implementar a igualdade estrutural e comparação como esperado.

Par e Triplet são existentes aulas de .net ver MSDN:

Triplet

Par

Recentemente, deparei com eles, enquanto a brincar com viewstate decodificação

Eu normalmente apenas criar minha própria estrutura, contendo os valores. É muitas vezes um pouco mais legível;)

KeyValuePair é a melhor classe para estender se você não quiser criar suas próprias 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;

Você pode estendê-lo a tantos níveis como você quer.

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

Nota : As classes Triplet e Par existe dentro do System.Web -dll, por isso não é muito adequado para outras soluções do que ASP.NET.

Você pode relativamente facilmente criar suas próprias classes tupla, a única coisa que potencialmente fica confuso é a sua igualdade e hashCode substituições (essencial se você estiver indo para usá-los em dicionários).

Deve-se notar que a própria estrutura KeyValuePair<TKey,TValue> da Net tem igualdade e hashCode métodos relativamente lentos .

Assumindo que não é uma preocupação para você ainda há o problema de que os fins de código por ser difícil de descobrir:

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?

Na maioria destes casos, eu encontrá-lo mais fácil de criar uma classe de registro específico (pelo menos até C # 4 faz este compilador-magic)

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

var retVal = GetSomething();

//get % progress
retVal.CurrentIndex / retVal.CurrentTotal;

Uma solução simples não tem sido mencionado ainda. Você também pode apenas usar um List<T>. Ele é construído em, eficiente e fácil de usar. Concedido, que parece um pouco estranho no início, mas ele faz o seu trabalho perfeitamente, especialmente para uma contagem maior de elementos.

NGenerics - do popular .Net algoritmos e estruturas de dados biblioteca, introduziu recentemente estruturas imutáveis ?? de dados para o conjunto.

Os primeiros imutáveis ??para implementar foram par e tuple classes. O código é bem coberto com testes e é bastante elegante. Você pode verificá- aqui . Eles estão trabalhando em outras alternativas imutáveis ??no momento e eles devem estar prontos em breve.

Não são construídos ins, mas um par classe é trivial para criar.

Sim, há System.Web.UI.Pair e System.Web.UI.Triplet (que tem um criador sobrecarregado para o comportamento Pair-tipo!)

Para o primeiro caso, eu costumo usar

Dictionary<KeyValuePair<string, int>, object>

Não são built-in classes para isso. Você pode usar KeyValuePair ou rolar para fora sua própria implementação.

Você pode usar System.Collections.Generic.KeyValuePair como sua implementação Pair.

Ou você poderia apenas implementar a sua própria, eles não são difíceis:

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

Claro, você pode algum dia correr em um problema que Triplo (string, int, int) não é compatível com Triplo (int, int, string). Talvez ir com System.Xml.Linq.XElement vez.

Há também o Tuple tipos em F #; você apenas precisa fazer referência FSharp.Core.dll.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top