2009-11-30 8 views
7

時々C#3.0でタプルの概念をシミュレートする方法を探していました。時間が経つにつれて、私は様々な "貧乏人の" 実装を持っていた、ここではそれらのほんの一部です:C#3.0タプル相当(男性用)

基本的なオブジェクトの配列

object[] poorTuple = new object[]{foo,bar,baz}; // basic object array 

より強くHoHoHo、型付き...

KeyValuePair<TypeA, KeyValuePair<TypeB, TypeC>> poorTuple; 

タイプ推論を使用できるクラスFunctional Programming for the Real Worldから持ち上げたもの)

を実装しています
public static class Tuple{ 
    public static Tuple<T1, T2> Create<T1 foo, T2 bar>{ 
    return new Tuple<T1, T2>(foo, bar); 
    } 
} 
// later: 
var data = Tuple.Create("foo", 42); 

質問:

  1. C#3.0(またはデータ構造を欠い選択した言語)で貧乏人のタプルを持っている任意の他の方法。

  2. とは何ですか? C#3.0でタプルを取得する方法 - 誰でもライブラリの勧告があれば歓迎します。

  3. リストやタプルのような特定のタイプではなく、特定のタイプを作成するのは理にかなっていますか? (親指のルールを探して)

答えて

8

あなたは便利な名前を除いて、タプルと同様に機能する匿名型を作成することができます。それは非常にに虐待されているので

var itemsWithChildCounts 
    = myObjects.Select(x => new { Name = x.Name, Count = x.Children.Count() }); 
+4

匿名型は、それを作成するメソッドの外部に渡すことはできません。 – Rory

+0

@Rory:それは完全に真実ではありません... http://msmvps.com/blogs/jon_skeet/archive/2009/01/09/horrible-grotty-hack-returning-an-anonymous-type-in​​stance.aspx ...それは同じアセンブリでのみ動作します。また、リフレクトトリックを使用することもできます(ASP.Net MVCフレームワークを参照してください) –

-2

私はC#で型推論を好みません短い書き込みのために。もちろん、それは非常にクールな機能ですが、人々はこの場合のようにIMHOを乱用します。

この場合、型に関する混同を避けるために、型を明示的に指定します(つまり、42は長いか、1バイトか短いか)。

なぜ単純なタプルクラスを持たないのでしょうか。これはほんの数行で実装できます。また、怠け者の場合は、タプルクラスの拡張メソッドを記述することもできます。これにより、生活が楽になりますが、よりクリーンになります。

あなたが提示した一般的なもの(型推論を除いて)の代わりに "空想的な"タプルクラスを持っていないのを見てください。

1

1 - 2の場合:自分のタプルクラスを実装することをお勧めします。あなたが盗んだ実装はまともなものです。それはうまくいくはずです。

3:これは私の経験則です - 複数のメソッド(同じ意味を持つ同じ型のもの)でこの機能を再利用したり、公開APIで使用するとすぐにあなたの特定の型で "本当の"クラスを実装する時が来ました。

0
  1. 方法はそれを得るために起こっているように良いです「クラスの実装」(と、それはとにかく、.NETの次のバージョンであるべき)
  2. ない考え、私は私自身の個人的なライブラリに保管してください今のクラス。
  3. 一般公開されるとすぐに(クラスの関連値を内部的に保存するために使用されなくなったとき)すぐに、適切なクラスを作成することを検討します。
0

あなたは意見を聞いたので、私は常にタイプを作成することになります。私はそうしない理由を理解できません。

多くの場合、タイプが実際に必要であることがわかります(主な用途は、2つのアイテムをコレクションに格納するか、メソッド呼び出しから2つのアイテムを返すことです)。あなたはおそらく何か間違っている)。

5

Bill Wagnerのarticle(2007年4月版)Visual Studio Magazineの汎用タプルのコードは次のとおりです。

public struct Tuple<T1, T2> : IEquatable<Tuple<T1, T2>> 
{ 
    private readonly T1 first; 
    public T1 First 
    { 
     get { return first; } 
    } 

    private readonly T2 second; 
    public T2 Second 
    { 
     get { return second; } 
    } 

    public Tuple(T1 f, T2 s) 
    { 
     first = f; 
     second = s; 
    } 

    #region IEquatable<Tuple<T1,T2>> Members 
    public bool Equals(Tuple<T1, T2> other) 
    { 
     return first.Equals(other.first) && 
      second.Equals(other.second); 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj is Tuple<T1, T2>) 
      return this.Equals((Tuple<T1, T2>)obj); 
     else 
      return false; 
    } 

    public override int GetHashCode() 
    { 
     return first.GetHashCode() ˆ second.GetHashCode(); 
    } 
    #endregion 
} 
0

あなたのプログラムに新しい値セットを導入することが理にかなっているときは、新しいタイプを作成することをお勧めします。たとえば、複雑な計算機を作成する場合は、複素数型を作成します。実際にちょっとした変数を一緒に「接着」したいのであれば、おそらくタプルが良い選択でしょう。私はそれが通常「ゲッター」関数は、戻り値を持つ場合理にかなっているが、中に考えて

static void GetNumbers(out int x, out int y) { ... } 
... 
int x, y; 
GetNumbers(out x, out y); 

:あなたが何かのようにするかもしれない...あなたは、コンソールからの2つの数値を収集し、単純な機能を持っているとしましょうこの場合、実際には2つの戻り値を持つことはできません。私は行って、TwoNumbersという新しいタイプを作ってそれを使うことができましたが、これは解決策よりもすぐに問題になると思います。 C#はタプルを持っていた場合、私は、次のような何かを行うことができるかもしれません:

static (int, int) GetNumbers() { ... } 
... 
int x, y; 
(x, y) = GetNumbers(); 

今本当に面白い質問です:C#は、この機能を持っていないが、私は図書館でそれを自分自身を実装することができていますか?あなたが提案するコードはスタートですが、私が2番目の例で行ったように割り当てを許可しません。私はC#についてはわかりませんが、戻り値が参照型の場合、代入演算子の左のオペランドには、という関数呼び出しを使用することができます。次のことを考えてみましょう:

// this class is implemented much like yours only with C++ 
template<typename T1, typename T2> class tuple { ... } 
... 
template<typename T1, typename T2> tuple<T1, T2>& tie(T1 a, T2 b) { ... } 
... 
template<typename T1, typename T2> tuple<T1, T2> get_numbers() { ... } 
... 
int x, y; 
tie(x, y) = get_numbers(); 

私たちはtie(x, y) =を持っている代わりに(x, y) =の...それはかなりくそ近いと思います。あなたは実装の詳細に興味があるなら、私はあなたが私が最初にこのことについて学んだTR1ライブラリを参照します:

http://www.boost.org/doc/libs/1_41_0/libs/tuple/doc/tuple_users_guide.html#tiers

だから、C#3.0にこのすべてのバックを持って...私たちは確かに作成することができますあなたが示してきたような汎用タプルクラスですが、C#でタプルを "解凍"するためのタイのような関数を作成できますか?私はそれを試していない、楽しいように聞こえる。そのようなことがなければ、私はC#タプルライブラリを自分のコードに増殖させることを嫌っています。

+0

この投稿にインスピレーションを与えたコードは、タプルから多くのマイレージを取得します(http://blogs.msdn.com/lucabol/を参照)。アーカイブ/ 2009/09/22/being-really-rich-with-c。aspx) - それは "ラフ"のコードだと主張することができますが、Bologneseはタプルを渡し、LINQ式と汎用プロパティを使用して個々の値の読み取りを行います。 – t3rse

+0

私はLucaの大ファンであり、彼は彼のタプルタイプで大きな成功を収めていると確信しています。私はあなたの想像力を傷つけ、自分自身に挑戦すれば、時には不可能と思われるものを取り除くことができるということを指摘していました。たとえば、Lucaのコードが次のような場合: var ticker = tuple.Item1; var name = tuple.Item2; var asset = tuple.Item3; var subAsset = tuple.Item4; は次のように記述できます var(ticker、name、asset、subAsset)=タプル; C#のように、それをサポートするには言語の更新が必要です。おそらく人々はC++と同じ考えをしていたが、誰かがそれを理解したのだろう。 –