• .NET

【.NET】タプル型の使い方

.NET Framework 4.7からタプル型(tuple)を使用できるようになりました。
タプル型とは複数の要素を一つの型として定義できるデータ構造です。
以下はC#でstring型、int型、bool型の組み合わせをタプル型変数として使用した例です。
※VBでも同じように使用できます

C#
            // 定義
            (string col1, int col2, bool col3) itm;

            // タプル型の値へ設定
            itm.col1 = "文字";
            itm.col2 = 1;
            itm.col3 = true;

            // タプル型の値を取得
            Console.WriteLine(itm.col1);
            Console.WriteLine(itm.col2.ToString());
            Console.WriteLine(itm.col3.ToString());
            
            // 同じ型であればタプル型ごと設定も可能
            (string col1, int col2, bool col3) itm2 = itm;

これだけみると定義以外は構造体を使うときと似ていませんか?
そう、タプル型は構造体の定義を1行で書けるものとわかれば大体正解です。単純なデータ型であれば構造体や内部クラスを作らなくていいので活用できればとても便利。またタプル型の独特の書き方として括弧内に型を定義するというのがポイントですね。書き慣れていないときは括弧が足りずコンパイルエラーになる人が多い印象です。

私は.NET Framework 4.xのシステムを10年ぐらい開発してきたバリバリの.NETエンジニアですが .NETにタプル型が追加されたことを知ったのは実は最近の話です。タプル型を知る前はDataTableをはじめ構造体や内部クラスを駆使して面倒なコードを書きまくっていましたが、タプル型を知ってからはコードを書く量が減ったおかげでストレスも減りました。

タプル型を使うとどのくらい省略して書けるのか比較してみます。
以下は3つのデータ型を持つ構造体に値を設定するコードです。

内部クラスを使用した例
C#
    class Program
    {
        static void Main(string[] args)
        {
            clsChild child = new clsChild();
            child.col1 = "a";
            child.col2 = "b";
            child.col3 = "c";

            Console.Write(string.Format("{0},{1},{2}",child.col1, child.col2, child.col3));
        }

        class clsChild
        {
            public string col1;
            public string col2;
            public string col3;
        }
    }
タプル型を使用した例
C#
    class Program
    {
        static void Main(string[] args)
        {
            (string col1, string col2, string col3) child;
            child.col1 = "a";
            child.col2 = "b";
            child.col3 = "c";

            Console.Write(string.Format("{0},{1},{2}",child.col1, child.col2, child.col3));
        }
    }

この違いがわかりましたか?タプル型だとこのぐらいスマートに書けるんです。なぜこれを早く知れなかったのか悔やまれます。

さらにこのタプル型は様々なことに応用できます。
例えばディクショナリ―クラスのKey、Valueは通常一つの項目しか指定できませんが、タプル型を使うとこの壁を簡単に突破できます。
以下はディクショナリ―のKeyに商品名、売上日を持たせて、売上金額を合計するサンプルです。

C#
        static void Main(string[] args)
        {
            // データテーブルを定義
            DataTable dt = new DataTable();
            dt.Columns.Add("ITEM_NAME", System.Type.GetType("System.String"));     //商品名
            dt.Columns.Add("SALES_DATE", System.Type.GetType("System.String"));    //売上日
            dt.Columns.Add("SALES_AMOUNT", System.Type.GetType("System.Decimal")); //売上金額

            // データテーブルにサンプルデータを設定
            DataRow dr1 = dt.NewRow();
            DataRow dr2 = dt.NewRow();
            DataRow dr3 = dt.NewRow();
            DataRow dr4 = dt.NewRow();
            DataRow dr5 = dt.NewRow();
            DataRow dr6 = dt.NewRow();
            dr1.ItemArray = new object[] { "みかん", "2025/04/01", 100 };
            dr2.ItemArray = new object[] { "みかん", "2025/04/01", 100 };
            dr3.ItemArray = new object[] { "りんご", "2025/04/01", 100 };
            dr4.ItemArray = new object[] { "みかん", "2025/04/02", 100 };
            dr5.ItemArray = new object[] { "りんご", "2025/04/03", 100 };
            dr6.ItemArray = new object[] { "りんご", "2025/04/03", 100 };
            dt.Rows.Add(dr1);
            dt.Rows.Add(dr2);
            dt.Rows.Add(dr3);
            dt.Rows.Add(dr4);
            dt.Rows.Add(dr5);
            dt.Rows.Add(dr6);

            // ディクショナリ―を定義
            Dictionary<(string ItemName , string SalesDate), decimal> dic = new Dictionary<(string ItemName, string SalesDate), decimal>();

            // 商品名、売上日ごとの売上金額を集計する
            foreach(DataRow dr in dt.Rows)
            {
                // ディクショナリ―に存在しない場合は追加する(売上金額は0で初期化)
                if (!dic.ContainsKey((dr["ITEM_NAME"].ToString(), dr["SALES_DATE"].ToString())))
                {
                    dic.Add((dr["ITEM_NAME"].ToString(), dr["SALES_DATE"].ToString()),0);
                }
                // 売上金額を加算する
                dic[(dr["ITEM_NAME"].ToString(), dr["SALES_DATE"].ToString())] += decimal.Parse(dr["SALES_AMOUNT"].ToString());
            }

            // 結果を出力
            foreach(var itm in dic)
            {
                Console.WriteLine(string.Format("商品名:{0} 売上日:{1} 売上金額:{2}", itm.Key.ItemName, itm.Key.SalesDate, itm.Value));
            }
        }

出力結果

商品名:みかん 売上日:2025/04/01 売上金額:200
商品名:りんご 売上日:2025/04/01 売上金額:100
商品名:みかん 売上日:2025/04/02 売上金額:100
商品名:りんご 売上日:2025/04/03 売上金額:200

タプル型を使用することによって今まで長々と書いていたコードもこれだけスマートに書けるのです。
この感動を一人でも多くの.NETエンジニアへ伝われば幸いです。

この記事は役に立ちましたか?

もし参考になりましたら、下記のボタンで教えてください。

コメント

この記事へのコメントはありません。