簡體   English   中英

在C#中使用一對(三重等)值作為一個值的最佳方法是什么?

[英]What's the best way of using a pair (triple, etc) of values as one value in C#?

也就是說,我想要一個價值元組。

我心中的用例:

Dictionary<Pair<string, int>, object>

要么

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

是否有內置類型,如Pair或Triple? 或者實施它的最佳方式是什么?

更新答案中描述了一些通用元組實現,但對於在字典中用作鍵的元組,您應該另外驗證哈希碼的正確計算。 在另一個問題中有關於此的更多信息。

更新2我想還值得提醒的是,當你在字典中使用某個值作為鍵時,它應該是不可變的。

內置類

在某些特定情況下,.net框架已經提供了類似元組的類,您可以利用它們。

對和三人組

通用的System.Collections.Generic.KeyValuePair類可以用作adhoc對實現。 這是泛型Dictionary在內部使用的類。

或者,您可以使用System.Collections.DictionaryEntry結構,該結構充當基本對,並具有在mscorlib中可用的優勢。 然而,不利的是,這種結構不是強類型的。

還可以以System.Web.UI.PairSystem.Web.UI.Triplet類的形式提供Pairs和Triple。 盡管這些類存在於System.Web程序集中,但它們可能非常適合winforms開發。 但是,這些類也不是強類型的,也可能不適用於某些場景,例如通用框架或庫。

更高階的元組

對於更高階的元組,如果沒有滾動自己的類,可能沒有一個簡單的解決方案。

如果已安裝F#語言 ,則可以引用包含一組通用不可變Microsoft.Fsharp.Core.Tuple類的FSharp.Core.dll ,直到通用的六進制文件。 但是,即使可以重新分發未修改的FSharp.Code.dll ,F#也是一種研究語言並且正在進行中,因此這種解決方案可能只對學術界有興趣。

如果您不想創建自己的類並且引用F#庫感到不舒服,那么一個很好的技巧可能在於擴展通用KeyValuePair類,以便Value成員本身就是嵌套的KeyValuePair。

例如,以下代碼說明了如何利用KeyValuePair創建Triples:

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;

這允許根據需要將類擴展到任意級別。

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

滾動你自己

在其他情況下,您可能需要求助於滾動自己的元組類,這並不難。

您可以創建簡單的結構,如下所示:

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

框架和圖書館

之前已經解決了這個問題,並且確實存在通用框架。 以下是一個這樣的框架的鏈接:

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

快進到2010年,.NET 4.0現在支持任意n的n元組 這些元組按預期實現結構上的平等和比較。

Pair和Triplet是.net中現有的類,請參閱msdn:

三聯

我最近遇到了他們,同時玩了viewstate解碼

我在C#中實現了一個元組庫。 訪問http://www.adventuresinsoftware.com/generics/並單擊“元組”鏈接。

我通常只創建自己的結構,包含值。 它通常更具可讀性;)

如果您不想創建自己的類, KeyValuePair是最好的擴展類。

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;

您可以將其擴展到任意數量的級別。

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

三聯存在的System.Web -dll中的類,所以它不是很適合ASP.NET比其他解決方案。

您可以相對輕松地創建自己的元組類,唯一可能變得混亂的是您的相等和哈希碼覆蓋(如果您要在字典中使用它們,則必不可少)。

應該注意的是.Net自己的KeyValuePair<TKey,TValue> struct具有相對較慢的相等和哈希碼方法

假設這不是你的問題,那么仍然存在代碼最終難以弄清楚的問題:

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?

在大多數情況下,我發現創建一個特定的記錄類更容易(至少在C#4使這個編譯器變得神奇之前)

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

var retVal = GetSomething();

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

尚未提及一個簡單的解決方案。 您也可以使用List<T> 它內置,高效且易於使用。 當然,它起初看起來有點奇怪,但它完美地完成了它的工作,特別是對於更多的元素數量。

NGenerics--流行的.Net算法和數據結構庫,最近向該集合引入了不可變數據結構。

實現的第一個不可變的是pairtuple類。 代碼完全覆蓋了測試,非常優雅。 你可以在這里查看 他們目前正在研究其他不可改變的替代方案,他們應該很快做好准備。

沒有內置的ins,但是Pair <T,R>類很容易創建。

是的,有System.Web.UI.Pair和System.Web.UI.Triplet(它有一個重載的對象類型行為的創建者!)

對於第一種情況,我通常使用

Dictionary<KeyValuePair<string, int>, object>

沒有內置的類。 您可以使用KeyValuePair或推出自己的實現。

您可以使用System.Collections.Generic.KeyValuePair作為您的Pair實現。

或者你可以實現自己的,他們並不難:

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

當然,有一天你可能會遇到Triple(string,int,int)與Triple(int,int,string)不兼容的問題。 也許改為使用System.Xml.Linq.XElement。

F#中還有Tuple <>類型; 你只需要參考FSharp.Core.dll。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM