ランタイムやライブラリの実装者向け、インライン配列(Inline arrays)が導入
C# 12では、struct型の固定長配列の利用が可能になりました。
メモリ利用における性能向上のために、C# 12ではInlineArray属性(System.Runtime.CompilerServices名前空間)が導入されました。この属性を付与された構造体は、パラメータに指定された要素数分の構造体配列(インライン配列=埋め込み配列)として機能します。通常の配列はヒープ上に領域が確保されますが、インライン配列ではスタック上に領域が確保されるので、メモリの確保や解放に伴うオーバヘッドを軽減できます。
コンパイラの機能強化というよりは、.NET 8ランタイムにおける機能強化です(サポートのためにコンパイラも変更を受けています)。
using System.Runtime.CompilerServices; [InlineArray(10)] struct Buffer { private int _value; (1) } var buffer = new Buffer(); for (int i = 0; i < 10; i++) { buffer[i] = i; (2) } foreach (var i in buffer) { (3) Console.WriteLine(i); }
このとき、(1)のように構造体の要素はただ1個である必要があります(2個以上記述するとコンパイルエラーとなります)。インライン配列のメリットは、ヒープを使わないこと、(2)のようにインデックスを使って構造体配列の要素に直接アクセスできるなど、従来の記法をそのまま使える点です。(3)のようにforeach文の対象とすることもできます。
この機能は、ランタイムやライブラリの実装者向けということになっています。.NETランタイムでは、コレクション式の実装に使われています。
実験的な機能を示すExperimental属性(Experimental attribute)が指定可能に
C# 12では、実験的機能を示す新しい属性Experimentalを指定可能になりました。
従来は、使おうとする型、メソッド、アセンブリ、モジュールが実験的な機能であるかを判断することはコード上は困難でしたが、C# 12で導入されたExperimental属性(System.Diagnostics.CodeAnalysis名前空間)により、コンパイル時に警告を発生することができるようになりました。この属性を付加された型やメンバは、実験的機能と見なされるようになります。モジュールやクラス、構造体にExperimental属性が指定されると、それが含む型やメンバも実験的な機能として扱われます。
Experimental属性は、例えば以下のリストのように指定します。
using System.Diagnostics.CodeAnalysis; [Experimental(diagnosticId: "TEST01")] (1) public class ExperimentalClass { public void print() { Console.WriteLine("This is Experimental Class"); } } var experimental = new ExperimentalClass(); (2)
(1)において属性のパラメータに指定されているdiagnosticIdは、コンパイラやIDEが使用する診断IDの指定です。コンパイラが出力するメッセージ、IDEが表示するメッセージの識別名として使用されます。複数箇所に属性を付与する場合、それらを識別する際に指定します。以下は、コンパイラが出力したエラーメッセージです(ソースファイルのパスは省略)。
…/experimental_attribute/Program.cs(6,24): error TEST01: 'ExperimentalClass' は、評価の目的でのみ提供されています。将来の更新で変更または削除されることがあります。続行するには、この診断を非表示にします。 […/experimental_attribute/experimental_attribute.csproj]
「error TEST01」と出力されているのが、diagnosticIdで指定した診断IDです。さらに、以下の図はVisual Studioのエラー一覧の表示です。
指定できるパラメータには他にUrlFormatがあり、ドキュメントのURLを設定、取得できます。
なお診断IDは、プロジェクト設定ファイルのNoWarnプロパティや、コード中のwarningプラグマによって、警告の抑制に使用できます。
<PropertyGroup> …略… <NoWarn>TEST01</NoWarn> </PropertyGroup>
プラグマは、警告を抑制したい範囲を囲むように、disableオプションとrestoreオプションとともに使用します。
#pragma warning disable TEST01 var experimental = new ExperimentalClass(); #pragma warning restore TEST01