そろそろ C# 12 の時期なので予習を始めなければなりません。
今回は .NET 8 RC1 が出たので、その環境で C# 12 を書いてみます。
> dotnet --version 8.0.100-rc.1.23455.8
ちゃんと RC1 環境です。
プロジェクトを作っていきます。
> dotnet new console
出来上がったファイルです。
> ls obj ConsoleAppNetRC1.csproj Program.cs
■ C# 12 のコードを書いてみる
作った C# 12 のコードを書いてみます。C# 12 のコードはこちらの記事から。
rksoftware.hatenablog.com
Program.cs
using System.Runtime.CompilerServices; using MyType = (int x, int y); // See https://aka.ms/new-console-template for more information Console.WriteLine(new Test("Hello, World! 1").Name()); Console.WriteLine(new MyType(1, 2)); int[] row0 = [1, 2, 3]; int[] row1 = [4, 5, 6]; int[] row2 = [7, 8, 9]; int[] single = [.. row0, .. row1, .. row2]; foreach (var element in single) { Console.Write($"{element}, "); } var lamda = (int a = 1) => a + a; Console.WriteLine(lamda()); var buffer = new Buffer(); for (int i = 0; i < 10; i++) { buffer[i] = i; } foreach (var i in buffer) { Console.WriteLine(i); } var c = new C(); c.InterceptableMethod(1); // (L1,C1): prints "interceptor 1" c.InterceptableMethod(1); // (L2,C2): prints "other interceptor 1" c.InterceptableMethod(2); // (L3,C3): prints "other interceptor 2" c.InterceptableMethod(1); // prints "interceptable 1" class Test(string name) { public string Name() { return name; } } [System.Runtime.CompilerServices.InlineArray(10)] public struct Buffer { private int _element0; } class C { public void InterceptableMethod(int param) { Console.WriteLine($"interceptable {param}"); } } // generated code static class D { [InterceptsLocation(@"C:\Sample\cs12\ConsoleAppVSPreview\ConsoleAppVSPreview\Program.cs", line: 36, character: 3)] // refers to the call at (L1, C1) public static void InterceptorMethod(this C c, int param) { Console.WriteLine($"interceptor {param}"); } [InterceptsLocation(@"C:\Sample\cs12\ConsoleAppVSPreview\ConsoleAppVSPreview\Program.cs", line: 37, character: 3)] // refers to the call at (L2, C2) //[InterceptsLocation(@"C:\Sample\cs12\ConsoleAppVSPreview\ConsoleAppVSPreview\Program.cs", line: 38, character: 3)] // refers to the call at (L3, C3) public static void OtherInterceptorMethod(this C c, int param) { Console.WriteLine($"other interceptor {param}"); } } namespace System.Runtime.CompilerServices { sealed class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }
.csproj は編集しないでやってみます。
■ .csproj は編集しない
> dotnet build MSBuild のバージョン 17.8.0-preview-23418-03+0125fc9fb (.NET) 復元対象のプロジェクトを決定しています... 復元対象のすべてのプロジェクトは最新です。 Program.cs(63,6): error CS9137: 試験的な機能である 'interceptors' が有効になっていません。'<Features>InterceptorsPreview</Features>' をプロジェクトに追加します。 Program.cs(69,6): error CS9137: 試験的な機能である 'interceptors' が有効になっていません。'<Features>InterceptorsPreview</Features>' をプロジェクトに追加します。 ビルドに失敗しました。
ビルドに失敗しました。
しかし見てください、構文エラーはありません! インターセプターが実験的機能過ぎて設定が必要と言われているだけです。
ということで、インターセプターを消してみます。
using System.Runtime.CompilerServices; using MyType = (int x, int y); // See https://aka.ms/new-console-template for more information Console.WriteLine(new Test("Hello, World! 1").Name()); Console.WriteLine(new MyType(1, 2)); int[] row0 = [1, 2, 3]; int[] row1 = [4, 5, 6]; int[] row2 = [7, 8, 9]; int[] single = [.. row0, .. row1, .. row2]; foreach (var element in single) { Console.Write($"{element}, "); } var lamda = (int a = 1) => a + a; Console.WriteLine(lamda()); var buffer = new Buffer(); for (int i = 0; i < 10; i++) { buffer[i] = i; } foreach (var i in buffer) { Console.WriteLine(i); } var c = new C(); c.InterceptableMethod(1); // (L1,C1): prints "interceptor 1" c.InterceptableMethod(1); // (L2,C2): prints "other interceptor 1" c.InterceptableMethod(2); // (L3,C3): prints "other interceptor 2" c.InterceptableMethod(1); // prints "interceptable 1" class Test(string name) { public string Name() { return name; } } [System.Runtime.CompilerServices.InlineArray(10)] public struct Buffer { private int _element0; } class C { public void InterceptableMethod(int param) { Console.WriteLine($"interceptable {param}"); } } // generated code static class D { // [InterceptsLocation(@"C:\Sample\cs12\ConsoleAppVSPreview\ConsoleAppVSPreview\Program.cs", line: 36, character: 3)] // refers to the call at (L1, C1) public static void InterceptorMethod(this C c, int param) { Console.WriteLine($"interceptor {param}"); } // [InterceptsLocation(@"C:\Sample\cs12\ConsoleAppVSPreview\ConsoleAppVSPreview\Program.cs", line: 37, character: 3)] // refers to the call at (L2, C2) //[InterceptsLocation(@"C:\Sample\cs12\ConsoleAppVSPreview\ConsoleAppVSPreview\Program.cs", line: 38, character: 3)] // refers to the call at (L3, C3) public static void OtherInterceptorMethod(this C c, int param) { Console.WriteLine($"other interceptor {param}"); } } namespace System.Runtime.CompilerServices { sealed class InterceptsLocationAttribute(string filePath, int line, int character) : Attribute { } }
■ 計画通り
> dotnet build ビルドに成功しました。
> dotnet run Hello, World! 1 (1, 2) 1, 2, 3, 4, 5, 6, 7, 8, 9, 2 0 1 2 3 4 5 6 7 8 9 interceptable 1 interceptable 1 interceptable 2 interceptable 1
計画通り実行までできました。
■ 言語バージョン
今回、.csproj に <LangVersion>Preview</LangVersion>
を書きませんでした。.NET 8 RC1 ではC# 12 はプレビュー機能ではなくなったという事ですね! 夢広がりますな~。
■ .NET 8 RC1
.NET 8 RC1 は Visual Studio のプレビュー版のアップデートでも入ります。素早くアップデートしましょう!