「out変数」とは、out引数を要求するメソッドを呼び出すとき、引数リストの中で変数宣言も行えるものだ。つまり、事前に変数を宣言しておかなくてよいのである。
例えば、文字列をDateTime型(System名前空間)に変換するTryParseメソッドは、その第2引数がout引数になっている。文字列をDateTime型に変換する(ただし、変換できないときは今日の日付を返す)メソッドは、従来なら次のコードのように書いていた。
public static DateTime ReadDate(string date)
{
// 文字列をDateTime型に変換する。変換できないときは、今日の日付を返す。
DateTime dt;
return DateTime.TryParse(date, out dt) ? dt : DateTime.Today;
}
C# 7では、TryParseメソッドを呼び出す式の中でout変数を宣言できる(次のコード)。そのため、事前の変数宣言が不要になるだけでなく、このような簡単なメソッドの場合は、ラムダ式での記述も可能になるのだ。
public static DateTime ReadDate(string date)
=> DateTime.TryParse(date, out var dt) ? dt : DateTime.Today;
なお、out変数のスコープは、その直前で変数宣言をしたときと同じになる。
C# 7の新しいタプルの機能を使うと、メソッドから複数の値を返せる。ただし、.NET Frameworkの追加機能を使っているため、.NET Framework 4.7以前の場合はコードを書いただけでは動かないので注意してほしい(後述)。
新しいタプルの機能を使うと、例えば次のコードのように合計と平均値を返すメソッドが作れる。
public static (int sum, double ave) Calc(IList<int> numbers)
=> (numbers.Sum(), numbers.Average());
上のメソッドは、次のコードのようにして使える。
(var sm, var av) = Calc(new int[]{1,3,5,7,9 });
Console.WriteLine($"合計={sm}, 平均={av:0.000}");
// 出力:合計=25, 平均=5.000
// varを使うときは、次のようにも書ける
var (s, v) = Calc(new int[] { 1, 3, 5, 7, 9 });
複数の値を返すメソッドなんて何が返ってくるか分からないという不安を抱くかもしれないが、心配はいらない。Visual StudioのIntelliSenseが、返値の名前もちゃんと教えてくれる(次の画像)。
C# 7の新しいタプルの機能は、ValueTuple構造体(System名前空間)に基づいている。ValueTuple構造体を作ったり、そこから値を取り出したりするコードの糖衣構文が、上で紹介したコードになるというわけだ。
このValueTuple構造体は、.NET Framework 4.7には組み込まれている。.NET Framework 4.7(またはそれ以降)を使っているときは、C# 7で上記のようなコードを書くだけでよい。
バージョン4.7よりも前の.NET FrameworkにはValueTuple構造体が組み込まれていない。そこでNuGetから「System.ValueTuple」パッケージをプロジェクトごとに導入する必要がある(.NET Core+Visual Studio Codeを使っている場合も同様)。忘れていると、タプルを使ったコードを書き始めた途端にエラーになってしまう。気を付けてほしい。
先の例では、メソッドから返値を受け取るところでタプルをいきなり分解していた。複数の値を受け取るだけなら、その方法で良いだろう。
メソッドから返された複数の値を、タプルのまま扱いたいときもある。タプルのまま他のメソッドに渡したいときなどだ。そのようなときは、分解せずにタプルとして受け取ることももちろん可能だ。また、タプルを構成する要素の名前が違うタプルに代入することもできる(次のコード)。
// 型と名前を指定してタプルの変数t1を宣言
(int sum, double ave) t1 = Calc(new int[] { 1, 3, 5, 7, 9 });
Console.WriteLine($"合計={t1.sum}, 平均={t1.ave:0.000}");
// varでタプルの変数t2を宣言(上と同じになる)
var t2 = Calc(new int[] { 1, 3, 5, 7, 9 });
Console.WriteLine($"合計={t2.sum}, 平均={t2.ave:0.000}");
// 名前が違うタプルの変数t3に代入する(それぞれの型が合っていればよい)
(int 合計, double 平均) t3 = t2;
Console.WriteLine($"合計={t3.合計}, 平均={t3.平均:0.000}");
今回は、C# 7の新機能の中から、簡潔なコーディングに役立つ4つの新機能の使い方を紹介した。ラムダ式でプロパティのsetterなども記述できるようになり、また、条件演算子などいくつかの式の中で例外を投げられるようになった。out引数を渡すところで同時に変数宣言が可能になった。新しいタプルの糖衣構文を使うと、複数の値を返すメソッドを簡潔に書ける。
Copyright© Digital Advantage Corp. All Rights Reserved.