Visual Studio (Win) で C# 7.2 が使えるらしいので試して見ました。
Visual Studio 2017 15.5 Preview 4 が必要らしいのでインストールします。
今の Visual Studio は同一メジャーバージョン/エディションでも複数インストールできるのではかどりますね。
■ C# 7.2 の設定
プロジェクトを新規に作成したらいつもの手順で、C# 7.2 を使えるように設定します。
プロジェクト > ××のプロパティ > ビルド > (右下の方の)[詳細設定]ボタン > 全般の[言語バージョン] を C# 7.2 に設定
これで、C# 7.2 が使えるはずです。
とりあえず今回は上記のリリースノートに書かれている機能を試してみました。
■ Span を試す
Span
var ary = Enumerable.Range(1, 10).ToArray(); var span = new Span<int>(ary, 2, 3); var readonlySpan = (ReadOnlySpan<int>)span; for (int i = 0; i < readonlySpan.Length; i++) Console.WriteLine(readonlySpan[i]); // 3 // 4 // 5 と出力される span[0] = 11; Console.WriteLine(readonlySpan[0]); // 11 と出力される // readonlySpan[0] = 21; ← これはエラー ary[2] = 31; Console.WriteLine(readonlySpan[0]); // 31 と出力される Console.ReadKey();
・Span
・Sapn
・最初に作った ary という配列の要素を変更した際に、Span
・Span
ちなみにこれ、System.Memory さえ参照すれば、C# のバージョンは関係ないみたいですね。C# 3 に変更しても動作します。
蛇足ですが、Span
■ readonly struct を試す
readonly struct SA { public readonly int PA; // public int PB; ← これはエラー public SA(int a) { PA = a; } // public void Set(SA a) { this = a; } ← これはエラー } struct SB { public readonly int PA; public int PB; // ← readonly でなければ OK public SB(int a, int b) { PA = a; PB = b; } public void Set(SB a) { this = a; } // ← readonly でなければ OK }
・readonly struct は readonly なメンバーしか持てない
・保持する値が変更されない(値が変更可能になる定義が禁止される)
■ in parameters / ref readonly returns を試す
struct SB { public int PA; public void Set(int a) => this.PA = a; } static ref readonly SB MyMethod(in SB a) { // a.PA = 11; ← 読み取り専用になるため値を変更できない // a = new SB(); ←読み取り専用になるため値を変更できない Console.WriteLine(a.PA); // 10 と出力される a.Set(12); // ←エラーにはならないが、読み取り専用になるため値を変更できない Console.WriteLine(a.PA); // 10 と出力される return ref a; } static void Main(string[] args) { var sb1 = new SB { PA=10 }; ref readonly var sb2 = ref MyMethod(sb1); Console.WriteLine(sb1.PA); // 10 と出力される Console.WriteLine(sb2.PA); // 10 と出力される sb1.Set(13); Console.WriteLine(sb1.PA); // 13 と出力される Console.WriteLine(sb2.PA); // 13 と出力される // sb2.PA = 14; // ←読み取り専用になるため値を変更できない sb2.Set(14); // ←エラーにはならないが、読み取り専用になるため値を変更できない Console.WriteLine(sb1.PA); // 13 と出力される Console.WriteLine(sb2.PA); // 13 と出力される Console.ReadKey(); }
これはちょっとルールが多くて複雑です。
とりあえずやりたいこととしては
・構造体を参照で渡してパフォーマンスを上げたいが、メソッド内/ return 先で書き換えられたくない場合に使う
・構造体を参照で渡しつつ、読み取り専用に制限できる
■ private protected を試す
次の二つの名前空間は別アセンブリにあるとします。
namespace ClassLibrary1 { public class Class1 { private protected void MyMethod() {; } } public class Class3 : Class1 { void MyMethod2() { base.MyMethod(); } // ← 同一アセンブリ内の派生クラスは OK } }
namespace AnotherAssemblyClass { class AnotherAssemblyClass : ClassLibrary1.Class1 { void MyMethod3() { // base.MyMethod(); ← これはエラー } } }
・同一アセンブリ内でのみアクセスできる
■ Non-trailing named arguments を試す
static void MyMethod(int a, int b, int c, int d) { ; } static void Main(string[] args) { MyMethod(1, 2, c:3, 4); // ← c の位置が順番とあっているので OK MyMethod(1, 2, d: 3, c:4); // ← 名前付きが後方に集まっているので OK // MyMethod(1, c: 2, b: 3, 4); // ← c、b の位置が順番とあっていないので NG MyMethod(d:1, c:2, b: 3, a:4); // ← 全て名前付きなので OK // MyMethod(1, c: 2, b: 3, a: 4); // ← a の位置は既に値が書かれている (1) ので NG }
・位置が順番とあっていれば、末尾でなくても引数に名前を付けられる
その他の 7.2 の機能
とりあえず、リリースノートに書かれている機能は確かに確認できそうです。
その他のリリースノートに書かれていない機能は、また後日試してみます。