20

つまり、値のタプルが必要です。

私の考えているユースケース:

Dictionary<Pair<string, int>, object>

また

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

Pair や Triple などの組み込み型はありますか? または、それを実装する最良の方法は何ですか?

更新回答で説明されている汎用タプルの実装がいくつかありますが、辞書でキーとして使用されるタプルについては、ハッシュコードの正しい計算をさらに検証する必要があります。それについての詳細は別の質問で。

更新 2ある値を辞書のキーとして使用する場合、それは不変でなければならないことも覚えておく価値があると思います。

4

16 に答える 16

20

組み込みクラス

特定のケースでは、.net フレームワークは、利用できるタプルのようなクラスを既に提供しています。

ペアとトリプル

汎用の System.Collections.Generic.KeyValuePair クラスは、アドホック ペアの実装として使用できます。これは、汎用 Dictionary が内部で使用するクラスです。

または、 初歩的なペアとして機能し、mscorlib で利用できるという利点を持つSystem.Collections.DictionaryEntry構造体を使用することもできます。ただし、欠点は、この構造が厳密に型指定されていないことです。

ペアとトリプルは、 System.Web.UI.Pairおよび System.Web.UI.Tripletクラスの形式でも使用できます 。これらのクラスはSystem.Webアセンブリに存在しますが、winforms 開発には完全に適している可能性があります。ただし、これらのクラスは厳密に型指定されているわけでもなく、汎用のフレームワークやライブラリなど、一部のシナリオには適さない場合があります。

高階タプル

高次のタプルの場合、独自のクラスをローリングしないと、簡単な解決策がない場合があります。

F# 言語をインストールしている場合は 、汎用の不変の Microsoft.Fsharp.Core.Tupleクラスから汎用の 6 組までのセットを含むFSharp.Core.dllを参照できます。ただし、変更されていないFSharp.Code.dll を再配布することはできますが、F# は研究言語であり、進行中の作業であるため、このソリューションは学界のみが関心を持っている可能性があります。

独自のクラスを作成したくなく、F# ライブラリを参照することに抵抗がある場合は、汎用の KeyValuePair クラスを拡張して、Value メンバー自体が入れ子になった KeyValuePair になるようにすることをお勧めします。

たとえば、次のコードは、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>();
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; }
    }
}

フレームワークとライブラリ

この問題は以前に対処されており、汎用フレームワークが存在します。以下は、そのようなフレームワークの 1 つへのリンクです。

于 2008-09-19T15:20:48.790 に答える
12
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;
}
于 2008-09-19T13:35:41.227 に答える
11

2010 年に早送りすると、.NET 4.0は任意の n の n タプルをサポートするようになりました。これらのタプルは、期待どおりに構造的等価性と比較を実装します。

于 2010-08-15T00:49:31.157 に答える
9

Pair と Triplet は、.net の既存のクラスです。msdn を参照してください。

トリプレット

ペア

ビューステートのデコードで遊んでいるときに、最近それらに出くわしました

于 2008-09-19T13:35:18.047 に答える
6

C# でタプル ライブラリを実装しました。http://www.adventuresinsoftware.com/generics/にアクセスし、「タプル」リンクをクリックします。

于 2008-09-19T13:38:26.557 に答える
3

私は通常、値を含む独自の構造体を作成します。多くの場合、もう少し読みやすいです;)

于 2008-09-19T13:33:45.427 に答える
2

独自のタプルクラスを比較的簡単に作成できます。厄介になる可能性があるのは、同等性とハッシュコードのオーバーライドだけです(辞書で使用する場合は必須です)。

KeyValuePair<TKey,TValue>.Net自体の構造体は、同等性とハッシュコードのメソッドが比較的遅いことに注意してください。

それがあなたにとって心配ではないと仮定すると、コードが理解するのが難しくなるという問題がまだあります:

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;
于 2008-09-19T16:14:22.250 に答える
2

1つの簡単な解決策はまだ言及されていません。を使用することもできますList<T>。内蔵されており、効率的で使いやすいです。確かに、最初は少し奇妙に見えますが、特に要素の数が多い場合は、完全に機能します。

于 2010-04-01T17:59:14.310 に答える
2

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

: クラスTripletおよびPairはSystem.Web -dll内に存在するため、ASP.NET 以外のソリューションにはあまり適していません。

于 2008-09-19T13:44:17.773 に答える
1

NGenerics - 一般的な .Net アルゴリズムおよびデータ構造ライブラリである NGenerics は、最近、セットに不変データ構造を導入しました。

最初に実装された不変クラスは、ペアクラスとタプルクラスでした。コードはテストで十分にカバーされており、非常にエレガントです。ここで確認できます。彼らは現在、他の不変の代替案に取り組んでおり、間もなく準備が整うはずです。

于 2009-11-02T16:50:11.303 に答える
0

組み込みはありませんが、Pair<T,R> クラスは簡単に作成できます。

于 2008-09-19T13:34:45.333 に答える
0

はい、System.Web.UI.Pair と System.Web.UI.Triplet があります (Pair 型の動作のオーバーロードされたクリエーターがあります!)

于 2008-09-19T13:35:47.857 に答える
0

最初のケースでは、私は通常使用します

Dictionary<KeyValuePair<string, int>, object>
于 2008-09-19T13:35:49.590 に答える
0

そのための組み込みクラスはありません。KeyValuePairを使用するか、独自の実装を展開できます。

于 2008-09-19T13:35:55.003 に答える
0

ペアの実装として System.Collections.Generic.KeyValuePair を使用できます。

または、独自のものを実装することもできますが、難しくはありません。

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 を使用してください。

于 2008-09-19T13:36:22.207 に答える
0

F# には Tuple<> 型もあります。FSharp.Core.dll を参照するだけです。

于 2008-09-19T13:42:58.887 に答える