今回はタプルについてです。
わりと新しめの機能で、データ型の1つになります。
タプル型の変数は一つの変数に複数の値を格納できます。
これを使うとメソッドの戻り値に複数の値を返せるようになったりします。
1つの変数で複数の値って配列もそうでは?と思うかもしれませんが、
配列は同じ型の変数をひとまとまりにするのに対し、
タプルは複数の型の変数をひとまとまりにすることができます。
タプルの使い方
いきなりですが使い方の前に、タプルには2つ種類があります。
名前付きのタプル と 名前のないタプル です。
名前付きのタプル
名前付きのタプルの宣言はこんな感じです。
// 名前付きのタプルの宣言
(int no, string name) named_tuple1 = (10, "abc");
// 代入するときに右辺で各フィールドの名前を付けられる
var named_tuple2 = (no: 20, name: "def");
かっこ ( ) の中に格納するデータ型をカンマ , で区切って2つ以上指定します。
格納される各データのことをフィールドと言います。
名前付きというのは各フィールドに名前が付いている、ということです。
データ型の後ろにフィールドの名前を指定します。
(データ型 フィールド名, データ型 フィールド名, … ) という感じです。
varを使う場合は、右辺側で名前を付けます。
var a = (フィールド名: 値, フィールド名: 値, … ) という感じです。
フィールド名と値の間はコロン : を付けます。
名前付きのタプルの値の取り出し方
タプルの各フィールドの値は、
タプル型の変数にドッド . を付けてフィールド名で取り出すことができます。
var named_tuple = (no: 20, name: "def");
System.Console.WriteLine(named_tuple.no);
System.Console.WriteLine(named_tuple.name);
20
def
名前のないタプル
名前のないタプルの宣言はこんな感じです。
// 名前のないタプルの宣言
(int, string) unnamed_tuple1 = (10, "abc");
// varを使うと右辺から型を判断してくれるので楽
var unnamed_tuple2 = (20, "def");
かっこ ( ) の中に格納するデータ型をカンマ , で区切って2つ以上指定します。
その際、フィールドの名前は指定しません。
名前のないタプルの値の取り出し方
名前のないタプルの各フィールドには、左から Item1、Item2、Item3、…と仮の名前がついているのでそれを使ってアクセスすることができます。
var unnamed_tuple = (10, "abc");
System.Console.WriteLine(unnamed_tuple.Item1);
System.Console.WriteLine(unnamed_tuple.Item2);
10
abc
タプルはnull許容型にできる
タイトル通りタプルは型の後ろに ? を付けてnull許容型にすることができます。
class Program
{
public static void Main()
{
// 通常のタプルはnullは代入できない
// (int, int) normal_tuple = null;
// null許容型にするとnullを代入できる
(int, int)? nullable_tuple = null;
}
}
null許容型についてはこちらを見てください。
タプルを分解して各フィールドを変数で受け取る
タプル型の各フィールドを分解してそれぞれの変数に値を代入することができます。
分解するには、タプルの各フィールドのデータ型に応じた変数を用意します。
かっこ ( ) 内に各フィールドに対応した型の変数を宣言します。
// 値がいっぱい入ったタプルを用意
(int, string, bool, double) tuple = (100, "abcde", true, 1.25);
// タプルの値を分解する
(int value1, string value2, bool value3, double value4) = tuple;
System.Console.WriteLine(value1);
System.Console.WriteLine(value2);
System.Console.WriteLine(value3);
System.Console.WriteLine(value4);
出力結果はこんな感じです、タプルが分解されてそれぞれの変数に格納されています。
100
abcde
True
1.25
タプルの分解にはいくつかやり方があります。
上で紹介した他に、
varを使うやりかたと、先に分割用の変数を宣言しておくやり方があります。
// 値がいっぱい入ったタプルを用意
(int, string, bool, double) tuple = (100, "abcde", true, 1.25);
// varを使った分割
var (value1, value2, value3, value4) = tuple;
// 先に分割用の変数を用意しておく
int field1;
string field2;
bool field3;
double field4;
(field1, field2, field3, field4) = tuple;
varを使った分割の仕方は、varの後ろにかっこ ( ) を付けてその中に変数を宣言します。
先に分割用の変数を宣言する場合は、それぞれのフィールドに対応した型の変数を宣言し、
かっこ ( ) の中に宣言した変数を対応順に指定します。
タプルを分解して必要な部分だけ変数で受け取る(破棄)
タプルを分解するときに必要なフィールドだけ変数に入れることができます。
必要のないフィールドのところはアンダーバー _ を指定します。
// 値がいっぱい入ったタプルを用意
(int, string, bool, double) tuple = (100, "abcde", true, 1.25);
// 分解してフィールド1、フィールド3だけ値を格納
var (value1, _, value3, _) = tuple;
System.Console.WriteLine(value1);
System.Console.WriteLine(value3);
100
True
複数の値を返すメソッドを作る
これがメインのタプルの使い道です。このためにタプルがC#に実装されたらしいです。
タプルが実装される前は、メソッドの戻り値で複数の値を返そうとすると、
戻り値用に複数のフィールドを持ったクラスを定義したり、out変数を使って引数に結果を格納する、なんてことをしていましたが、タプルがあれば解決です。
class Program
{
// 名前なしタプルを返すメソッド
public static (int, int) TestMethod_unnamed() {
return (10, 20);
}
// 名前ありタプルを返すメソッド
public static (int value1, int value2) TestMethod_named() {
return (100, 200);
}
public static void Main()
{
// タプルを使って複数の値を戻り値と受け取れる
var a = TestMethod_unnamed();
System.Console.WriteLine(a.Item1); // 名前なしタプルなのでItem*でアクセス
System.Console.WriteLine(a.Item2);
// メソッドの戻り値のタプルを分割して表示、なんてこともできる
(var val1, var val2) = TestMethod_unnamed();
System.Console.WriteLine(val1);
System.Console.WriteLine(val2);
// こっちは名前付きタプルが返ってくる
var b = TestMethod_named();
System.Console.WriteLine(b.value1);
System.Console.WriteLine(b.value2);
}
}
出力結果はこんな感じ、一度に2つの値を戻り値として返しています。
10
20
10
20
100
200
タプル同士の等値判定(== !=)
タプル同士で等値判定をしてみます。
var t1 = (10, "abc", true);
var t2 = (val1: 10, val2: "abc", true);
System.Console.WriteLine(t1 == t2);
System.Console.WriteLine(t1 != t2);
出力結果は・・・
True
False
等値と判定されました。
タプルは名前のありなしの関係なしに、各フィールドが等値であるかを判定しています。
また、右辺と左辺のフィールドの数が一致していないとエラーになります。
var t1 = (10, "abc", true);
var t2 = (10, "abc", true, 1.25);
System.Console.WriteLine(t1 == t2); // エラーになって実行できない
C# 記事まとめページに戻る(他のサンプルコードもこちら)
コメント