C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2010/10/26 20:58

.NET クラスライブラリ探訪-038 (System.Tuple)(タプル, 組オブジェクト, 4.0から追加されたクラス) - いろいろ備忘録日記

個人的には以前 今更 Func デリゲートや Action デリゲートについて一言 に書いた理屈と同様に、Tuple も無闇には使わずクラス内部のみといった限定的な利用に留めておくのが良いと考えていますが、Tuple の活用シーンは結構あるのではないかと思います。

Tuple は配列と少し似ていますが、次のような違いがあります。
  • 長さ毎に型が用意されている
  • 各要素は厳密に型付けされる
  • 各要素は読み取り専用
  • Tuple の Equals メソッドは各要素の等値性を比較する
  • Tuple の GetHashCode メソッドは各要素を元にハッシュコードを導出する
特に、下2つが中々に利用価値を高めていると思います。
Tuple は配列やコレクションと違って、同一性ではなく等値性で区別されます。これにより、Tuple を Dictionary の複合キーとして使用することができます。

private Dictionary<Tuple<int, int>, string> _dict;

public string GetValue(int key1, int key2)
{
    return this._dict[Tuple.Create(key1, key2)];
}


また、自作クラス/構造体の Equals メソッド及び GetHashCode メソッドをオーバーライドする時、全てのフィールドをセットした Tuple に処理を委譲することで実装を容易にすることができます。

public sealed class Class1
{
    public Class1(int arg1, string arg2)
    {
        this._field1 = arg1;
        this._field2 = arg2;
    }

    private readonly int _field1;
    private readonly string _field2;

    public override bool Equals(object other)
    {
        var otherAsClass1 = other as Class1;
        if (otherAsClass1 == null)
        {
            return false;
        }

        var thisFieldTuple = this.CreateFieldTuple();
        var otherFieldTuple = otherAsClass1.CreateFieldTuple();

        return thisFieldTuple.Equals(otherFieldTuple);
    }

    public override int GetHashCode()
    {
        var fieldTuple = this.CreateFieldTuple();
        return fieldTuple.GetHashCode();
    }

    private Tuple<int, string> CreateFieldTuple()
    {
        return Tuple.Create(this._field1, this._field2);
    }
}


ということで、Tuple は使い方次第でかなり重宝するかもしれません。
タグ: .NET C#


なるほど・・Dictionaryの複合キーに使うのは全然思いつきませんでした。これはアリですね。勉強になりました。 m(_ _)m

2010.10.27 02:23 URL | gsf_zero1 #Iwrm9LII [ 編集 ]


僕も昨日までは Tuple を使う機会はあんまないと思っていたんですが、使い捨てコードで Tuple 乱用していたら複合キーとして使用できることに気づきました^^;

2010.10.27 12:59 URL | よこけん #Ay6tTHf6 [ 編集 ]


タプルは、IEnumerable に Zip を拡張 (4.0から導入された Zip は ZipWith と改名してほしい・・・) して、Where とかを、

public static IEnumerable<Tuple<T1, T2>> Where(this IEnumerable<Tuple<T1, T2>> self, Func<T1, T2, bool> predicate)
{
return self.Where(t => predicate(t.Item1, t.Item2));
}

みたいに拡張して使ってます。

names.Zip(ages).Where((name, age) => name.Length > 5 && age > 10);

な感じで、タプルの ItemN プロパティを使わずにいい感じの名前を付けることができます。
これだと 2 要素タプルのみなので、T4 使って自動生成するといい感じに。

2010.10.28 09:14 URL | bleis-tift #sqCyeZqA [ 編集 ]


なるほど!
Zip の拡張ってのはこんな感じですね。

public static IEnumerable<Tuple<T1, T2>> Zip<T1, T2>(this IEnumerable<T1> self, IEnumerable<T2> second)
{
 return self.Zip(second, ((item1, item2) => Tuple.Create(item1, item2)));
}

これ、BCL で用意してくれればいいのに。。。

2010.10.28 19:31 URL | よこけん #Ay6tTHf6 [ 編集 ]












トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/290-3cd9c1c1