このエントリーは「C# Advent Calendar 2013」の21日目のエントリーです。
前日はterry_u16さんの「【C#】niconicoAPIを使ったりスクレイピングしたり」でした。
今回は時間がなくなってしまって、ちょこっとした内容ですが…。
さて、本年2回めのC# Advent Calendarですが、以前からずっと気になっていたクラスの1つでTupleクラスがあります。
まず、Tupleクラスについて簡単にご説明するところから始めましょう。
Tupleクラス
Tupleとは組みを表す単語で、語源は確かDoubleとかTrippleなどの組み合わせの数字がおおきくなってくるとquintuple(5組み)、sextuple(6組)と増えていく中、徐々に表現しずらくなることから10tuple、11tupleという表現となった・・・と聞いたことがあります(不確定ですみません(^^;)
.NET Framework においては.NET Framework 4より、名前が不確定な複数のオブジェクトをのひとかたまり(1組み)を表現するのにTupleクラスが追加されました。。
利用方法はGenericのメソッドにより生成する形になります。
Tuple.Create<T1>(T1)
Tuple.Create<T1, T2>(T1, T2)
Tuple.Create<T1, T2, T3>(T1, T2, T3)
Tuple.Create<T1, T2, T3, T4>(T1, T2, T3, T4)
Tuple.Create<T1, T2, T3, T4, T5>(T1, T2, T3, T4, T5)
Tuple.Create<T1, T2, T3, T4, T5, T6>(T1, T2, T3, T4, T5, T6)
Tuple.Create<T1, T2, T3, T4, T5, T6, T7>(T1, T2, T3, T4, T5, T6, T7)
Tuple.Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1, T2, T3, T4, T5, T6, T7, T8)
生成されるオブジェクトは構造体であり、値型です。
12/23追記:生成されるTuple自体はクラスから生成された参照型のオブジェクトでした。失礼しました。
http://msdn.microsoft.com/ja-jp/library/vstudio/dd386941%28v=vs.110%29.aspx
http://msdn.microsoft.com/ja-jp/magazine/dd942829.aspx
(いげ太さん、ご指摘いただいたありがとうございました)
これに似たような機能としてKeyValuePair構造体がありました。KeyValuePairがKeyとValueのデータを保持するのに対して、Tupleは最大8つの値を保持することが可能で、各項目の取り出しは以下のような形で行えます。
var tupleData1 = Tuple.Create<int, int, int>(1, 2, 3);
Console.WriteLine(tupleData1.Item1);
Console.WriteLine(tupleData1.Item2);
Console.WriteLine(tupleData1.Item3);
//こうでも大丈夫
var tupleData2 = Tuple.Create(1, 2, 3);
Console.WriteLine(tupleData2.Item1);
Console.WriteLine(tupleData2.Item2);
Console.WriteLine(tupleData2.Item3);
実行結果は以下の通りです。
このように利用方法はとても簡単です。 そのため、テスト用のデモアプリを作ったりする場合には非常に重宝しています。
また、メソッドから複数の値を返す場合にカスタムクラスを作ったり、outパラメータを使ったりしなくても、Tupleで用が足りそうです。
が! いざ、業務で開発するような場合はコレクションなどと異なって、使いどころがなかなか難しい。 だいたいの要件は匿名クラスで足りるでしょうし、敢えて戻り値で返すならきちんとカスタムクラスを定義したほうがよさそう…。
見ての通り、各項目の取り出しは「Item1, Item2…」といった特に名前に特徴のないプロパティによってマジック変数化してしまって難読化されてしまうのが難点。
ただ、単体テストとかならなんとか利用できるのではないか…と思ってやってみました。
テストの対象はこちら。
namespace ClassLibrary1
{
public class Class1
{
public static int Add(int x, int y)
{
return x + y;
}
}
}
で、単体テストはというと…。
using System;
using System.Collections.Generic;
using ClassLibrary1;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var testCase = new List<Tuple<int, int, int>>()
{
Tuple.Create(1, 1, 2),
Tuple.Create(2, 1, 3),
Tuple.Create(1, 2, 3)
};
testCase.ForEach(c => Assert.AreEqual(Class1.Add(c.Item1, c.Item2), c.Item3));
}
}
}
こんな感じ。
んー、やはり匿名クラスでもよい気がしますが…判断はおまかせします(^^;
というワケで、結論のないエントリですみません。
21日目のエントリーは以上になります。
次はmoririringさんです!よろしくお願いします!