「Any Developer, Any App, Any Platform」 ―― Visual Studio 2017が目指す世界とは?:特集:Visual Studio 2017の全貌を探る(2/5 ページ)
Visual Studio 2017はもはやWindowsアプリ開発者のためだけのものではない。その新機能と、実際にどんなアプリを開発できるのか見てみよう。
2. Dev Basics(言語/ユニットテスト/.NET Standard)
現代のソフトウェア開発では、ソースコードの読み書き/テスト/デバッグだけでなく、プロジェクト管理システムの利用や、自動化されたユニットテストの作成/実施なども基礎的なスキルと見なされるようになってきた。プロジェクト管理システムは上で述べたので、ここではVS 2017のプログラミング言語とユニットテストの新機能を紹介する。また、新しい形式のクラスライブラリ「.NET Standard Library」もVS 2017でサポートされたので、それもここで紹介しておこう。
言語の新機能
VS 2017では次の言語が新バージョンになっている。C# 7/Visual Basic 15/F# 4.1。また、2016年12月にリリースされたばかりのTypeScript 2.1も標準で組み込まれた。Pythonは遅れて提供されるようだ(本稿執筆時点では「Visual Studio Preview」には含まれている)。
中でも進化が大きいのはC# 7だ(その機能の一部はVisual Basic 15にも導入されている)。その新機能から幾つかを紹介しよう。なお、MSDNの日本語ドキュメントがまだ完備されていないため、用語の日本語訳は仮のものである(VS 2017のリリースノートの「C# および Visual Basic」の項にあるものはそれに従った)。
- 値タプル(value tuples): これを利用すると、メソッドから複数の値を返せる。タプルは.NET Framework 4.0からあるのだが、C# 7の値タプルで格段に使いやすくなった
値タプルを取り上げている記事
- Dev Basics/Keyword:タプル
- .NET TIPS:foreachループで現在の繰り返し回数を使うには?[C#/VB](値タプルの利用例を解説した改訂版の記事を2017年3月23日に公開)
- 入れ子になったローカル関数(nested local functions): メソッドの中に関数(=メソッド)を定義できるようになった。メソッドをメソッドの中にカプセル化(隠蔽)できるわけだ
- 数値の桁区切り(digit separators): 数値リテラルの途中に、桁区切りを表す「_」を書ける(コンパイル結果には影響しない)
- 2進数リテラル(binary literals): 接頭辞「0b」を付加することで、2進数表現になる
以上の新機能を使ったサンプルコードを次に示そう。タプルやローカル関数の使い方、接頭辞「0b」と桁区切りの「_」を使用して2進数値を表記しているところなどに注目されたい。
static void Main(string[] args)
{
// 値タプルを受け取ると同時に、ローカル変数indexとnameへ分解
var (index, name) = LocalFunc1();
WriteLine($"{index}, {name}");
// 出力:123, aaa
// ローカル関数(呼び出しているところより後に書いても構わない)
// この返値は値タプル(indexとnameをいっぺんに返す)
(int index, string name) LocalFunc1()
{
// 数値リテラルの2進数表記と、桁区切り
return (0b0111_1011, "aaa");
}
}
コンソールアプリ用のコードである。
次の準備が必要:
- コードの冒頭に「using static System.Console;」を記述。
- NuGetからSysytem.ValueTupleパッケージを導入(.NET Framework 4.7からは不要になるもよう)。
- 参照返しと参照ローカル変数(ref returns and locals): メソッドの戻り値を参照返ししたり、ローカル変数に参照としてそれらを保存したりできるようになった。値型(整数型や構造体など)も参照で扱える
参照返しと参照ローカル変数の利用例を以下に示す。参照渡しされる値を取り扱うには、戻り値型や、実際のメソッド呼び出し、戻り値を保存するローカル変数の宣言に「ref」キーワードを指定する必要がある。この例では、変数mの値が1/変数nの値が3なので、RefMin関数はパラメーターxに受け取った値(パラメーターも「ref」宣言されているので、これは参照渡しされた変数mそのものである)を参照返しする。よって、これを受け取る「ref int min」として宣言された参照ローカル変数minは以前に宣言している変数mを参照することになるので、「min = 5」により変数mの値も変更されることになる。
static void Main(string[] args)
{
// 参照返しをするローカル関数
ref int RefMin(ref int x, ref int y)
{
if (x < y)
return ref x;
return ref y;
}
int m = 1, n = 3;
ref int min = ref RefMin(ref m, ref n);
// minは参照ローカル変数
min = 5;
// minはmを参照しているので、minに代入することはmに代入することになる
WriteLine($"m={m}, n={n}");
// 出力:m=5, n=3
}
コンソールアプリ用のコードである。
次の準備が必要:
- コードの冒頭に「using static System.Console;」を記述。
- パターンマッチング拡張機能(pattern matching extensions): is演算子の構文を拡張して、型が一致しているときはその場に宣言した変数に代入できるようになった。また、switch文でもその構文を拡張してcaseに型やnullを指定できるようになった。型が一致しているときはその場に宣言した変数に代入できる
パターンマッチングを行う例を以下に示す。例えば、最初の「case Line l」節ではパラメーターshapeの型が比較され、それがLine型である場合に、そこで宣言されている変数lにshapeが代入される。そして、変数lの型は今比較をしたLine型となっているので、その後でキャストを行う必要なしにそれをLine型のオブジェクトとして利用できるというわけだ。
void WhatShape(Shape shape)
{
switch (shape)
{
case Line l:
// ここに来たときは、shape変数がLine型にキャストされて変数lに入っている
Debug.WriteLine($"({l.X1},{l.Y1})と({l.X2},{l.Y2})を結ぶ線です");
break;
case Ellipse e when e.Width == e.Height:
// when句でさらに条件を付けられる
Debug.WriteLine("円です");
break;
case Ellipse e:
// 上から順にcaseが試されるので、円のときはここには来ない
Debug.WriteLine("だ円です");
break;
case null:
Debug.WriteLine("nullです");
break;
default:
// shape変数がnullのときは上の「case null:」に流れるので、ここには来ない
// ここではnullチェック抜きでshape変数を使える
Debug.WriteLine($"{shape.GetType().Name}です");
break;
}
}
WhatShape(new Line { X1 = 0.0, Y1 = 0.0, X2 = 1.0, Y2 = 1.0 });
WhatShape(new Ellipse { Width = 10.0, Height = 10.0 });
WhatShape(new Ellipse { Width = 5.0, Height = 10.0 });
WhatShape(new Rectangle { Width = 5.0, Height = 10.0 });
WhatShape(null);
// 出力:
// (0,0)と(1,1)を結ぶ線です
// 円です
// だ円です
// Rectangleです
// nullです
WPFアプリ用のコードである。
ここまでC#の新機能についてざっくりと見た。次ページでは、ユニットテストと.NET Standardについて紹介しよう。特に、VS 2017 Enterpriseで提供されるライブユニットテストは(テストコードを書けば)コード記述と同時にユニットテストを自動的に行ってくれるというすぐれものだ。
Copyright© Digital Advantage Corp. All Rights Reserved.