はじめに
現在私はXD.GROWTHで主にGo言語を使っています。
長らくC#から離れています。
最後に本格的に触っていたのは C# / .NET Framework 3.5 の頃です。
Go言語を使っていると、C#ならこんな書き方できるのになぁと思うことも多々あります。
このシリーズでは数回に分けてC#を久しぶりに触ってみて
- 「こんな書き方ができるようになったのか」と驚いた点
- 久しぶりに触ってみて、正直「やっぱり不便だな」と感じた点
を中心に、コードを交えながら紹介します。
今回のテーマ
この記事では、タプルについて扱います。
Go言語では当たり前のように使うことができる複数の戻り値。
// [Go言語]
func ParseDrive() (string name, bool has) { ... }
.NET 3.5 時代であれば、複数の変数を戻り値として返したいとき、
- クラスや構造体を作る
- out や ref 引数を使う
といった手段しかありませんでした。
それがC#ではタプルという形で実現されていました。
// [C#]
(string name, bool has) ParseDrive() { ... }
でもこれの実体って、ValueTupleっていう構造体なので、
Go言語のように、別々の値をスタックに積んでいるわけではないんですよね。。。
呼び出し側では
// [C#]
(string name, bool has) = ParseDrive();
if (has) {
Console.WriteLine(name);
}
と、分割して受け取ったり
// [C#]
var drive = ParseDrive();
if (drive.has) {
Console.WriteLine(drive.name);
}
と 構造体のように自然にアクセス できます。
当時、タプルという言葉もなく(知らなかっただけかも?)
LINQのselectの戻り値としてよく使っていたなぁという記憶がありました。
タプルは型なので、関数の戻り値にする他、
ジェネリックの型パラメータとして使用することも出来ます。
// [C#]
private readonly Lazy<(string name, bool has)> _drive;
private readonly Lazy<(string path, bool absolute)> _root;
最後に
「戻り値は1個まで」という制約を、言語仕様で力技突破した感があって面白いですね。
いかがだったでしょうか。
ご意見ご感想などありましたら、いただけると作者は喜びます。