#タプルってなんだべ。んめもんだか?
VisualStudio2017のC#(C# Ver7.0)から本格的に組み込まれた、「タプル(Tuple)」。
大変便利で、拙作ソフトウェアでは結構多用しているが、まだあまりピンと来ない人がまだ多そうなので、東方っぽい例を出しながら紹介していきたいと思う。
ちなみに、.NETFramework4.0以上ならタプルは使用可能。
7や8.1向けのアプリケーションにtupleを組み込みたい場合は、NuGetからSystem.ValueTupleをダウンロードすると良い。
「タプル」の原義については、Wikipedia先生が詳しいのでそちらに譲る事にする。
##つまりどういうことなんだってばよ?
簡単に言えば、複数の値をペアにして扱える構文である。
// 何の数字かはお察しください...
var tuple = ("鍵山雛", 50, 45, 49);
という感じである。
簡易二次元配列とか簡易クラスと捉えるとしっくりくるかも。
#基本的な使い方
例えば、こういうアヤシイクラスがあったとしよう。
public class Character {
public string Name { get; set; }
public string Category { get; set; }
private int Tall;
private int Bust;
private int Waist;
private int Hip;
public Character(int t, int b, int w, int h) {
Tall = t;
Bust = b;
Waist = w;
Hip = h;
}
}
そして、これまたアヤシイCharacterクラスのオブジェクトの配列がある。
// 数値については異論を認める
var Fujinroku = new Character[] {
new Character(162, 84, 52, 83) {
Name = "秋静葉",
Category = "東方風神録"
},
new Character(163, 94, 62, 81) {
Name = "秋穣子",
Category = "東方風神録"
},
new Character(172, 94, 57, 89) {
Name = "鍵山雛",
Category = "東方風神録"
},
new Character(161, 88, 52, 91) {
Name = "河城にとり",
Category = "東方風神録"
},
new Character(165, 86, 64, 83) {
Name = "犬走椛",
Category = "東方風神録"
},
new Character(169, 92, 55, 88) {
Name = "射命丸文",
Category = "東方花映塚"
}
new Character(168, 94, 65, 94) {
Name = "東風谷早苗",
Category = "東方風神録"
},
new Character(176, 88, 60, 88) {
Name = "八坂神奈子",
Category = "東方風神録"
}
new Character(152, 79, 52, 80) {
Name = "洩矢諏訪子",
Category = "東方風神録"
}
};
さて、ここからプライベートプロパティを取り出す実装をするという事を考えてみる。
従来のやり方では、きっとこうだろう。
// 一つずつGetterを作るのは面倒だよね
public int GetTall() {
return Tall;
}
タプルを使うと、こういうことができる。
// プロパティを根こそぎ浚える
public (int, int, int) GetThreeSize() {
return (Bust, Waist, Hip);
}
つまり、例の配列から雛ちゃんのスリーサイズを得るには、こうする。
var HinaChangNoThreeSize = Fujinroku[2].GetThreeSize();
##セッターにも使えるぞ
Getが出来るってことは、当然Setも出来る。
さっきのアヤシイクラスを拡張して、
public class CharacterWithColors : Character {
private string Hair;
private string Eye;
private string Pants;
public void SetColor((string, string, string) colors) {
Hair = colors.Item1;
Eye = colors.Item2;
Pants = colors.Item3;
}
}
とすれば、髪の色、目の色、おぱんつの色をTupleでセットできるようになる。
var UdonChang = new CharacterWithColors(173, 92, 56, 84) {
Name = "鈴仙・優曇華院・イナバ",
Category = "東方永夜抄"
}
// ぱんつはいてません
UdonChang.SetColor(("#DA81F5", "#FE2E2E", null));
#ちょっと応用
分解
C#7.0以降では、タプルの値を簡単に分解できるようになった。値ってば最強ね
例えば、さっきの雛ちゃんのスリーサイズをint3つにバラすには、こうする。
// ローカル変数と同じ扱いなので、雛ちゃんのスリーサイズは同一スコープ内で利用できる
(int Bust, int Waist, int Hip) = HinaChangNoThreeSize;
// 直接メソッドから取ることもできる
(Bust, Waist, Hip) = Fujinroku[2].GetThreeSize();
オブジェクトっぽく扱う
Listにもできる。工夫次第ではJavaのLinkedHashMapみたいなアレもできる。
var tupleList = new List<(int, Character)>();
// 世界一位
tupleList.Add((1, new Character(171, 89, 52, 88) {
Name = "博麗霊夢",
Category = "自機"
}));
// 悔しいので来年は抜いてやるぜ
tupleList.Add((2, new Character(167, 84, 57, 90) {
Name = "霧雨魔理沙",
Category = "自機"
}));
:
:
// ⑨位でいいの。謙虚だもの私
tupleList.Add((9, new Character(174, 92, 63, 91) {
Name = "アリス・マーガトロイド",
Category = "東方妖々夢"
}));
:
:
Linqで使う
タプルの配列はLinqで抽出とかも簡単にできる。
// int, Characterのタプルリストから上位10キャラの名前を取得
tupleList.Where(tuple => tuple.Item1 <= 10).Select(tuple => tuple.Item2.Name);
/*
今年のサンプルだと、
---
博麗霊夢
霧雨魔理沙
古明地こいし
魂魄妖夢
十六夜咲夜
フランドール・スカーレット
レミリア・スカーレット
古明地さとり
アリス・マーガトロイド
藤原妹紅
---
となる。
*/
#まとめ
あれっ、もうDictionaryオワコンじゃね……?