Null許容参照型と制限付き多重継承を含む、C# 7.2 と 8.0のための機能がすでに準備されている。
読み取り専用の参照型と構造体 [7.2 プロトタイプ]
まずは読み取り専用の参照型と構造体だ。簡単にいうと、これによってC#はconstのようなパラメーターを使用してパフォーマンスを向上させる能力を手にする。“ref readonlyパラメーター”や、単に“inパラメーター”として知られ、これらは大規模な構造体が参照渡しされることを許可し、一方で変更は許可しない。
この提案の一部には読み取り専用の構造体が含まれる。構造体にreadonlyのマークをつけることで、開発者はその構造体におけるどのメソッドも、その構造体を変更することができないことを明示する。これはパフォーマンスに影響を与える。コンパイラーに対して、読み取り専用変数が変更されることを防ぐために通常行っているように、コピー処理をスキップできることを明示するためだ。
Blittable型 [7.2 提案]
Wikipediaはblittable型を以下のように説明している。
Microsoftの.NET Frameworkにおいて、データは通常マネージドとアンマネージドのコードで異なってメモリに表現される。しかし、blittable型はいずれの環境でも同様にメモリで表現されるように定義され、直接共有することができる。
非blittable型にはBoolean, string, charと任意の参照型が含まれる。構造体がこれらの型のいずれかを含む場合、その構造体自身も非blittableとなる。
現在、C#のコンパイラーは与えられた型がblittableかそうでないかを、その構造を検査することによって推測する。これは過去に問題を引き起こしていた。新しいフィールドを追加することでblittable型が非blittable型になってしまう可能性があり、環境によっては破壊的変更となってしまう。
Blittable Typesの提案では、“blittable”キーワードを付与することでその構造体がblittableであることを明示できる。その型が非blittableとなるような変更があれば、コンパイラーエラーが発生する。
長期間の後方互換を保証するため、blittableとしてマークされた構造体は、同様にblittableとして明示された構造体のみ含めることができることになるかもしれない。さらに、構造体はStructLayout(LayoutKind.Auto)を使用できなくなるかもしれない。これは構造体がメモリにおいてどのように物理的に配置されるかに言及する。明示的レイアウト、順序的レイアウトが指定可能だ。
注釈: 構造体においてLayoutKindまたはPackの設定を変更することは破壊的変更として考えられる。アンマネージドコードからみた構造体が変わるためだ。
Microsoftはこの機能のための移行期間について懸念している。低レベルなライブラリは、より高レベルなライブラリが明示的blittable型を使用し始める前に対応する必要がある。
ref-like型のための安全なコンパイル時間強制 [7.2 提案]
このC#の機能は“内部ポインター”または“ref-like型”としても知られる。この提案は、Span<T>のような特定の型がスタックにのみ現れるようにコンパイラーに強制させることができるようにするというものだ。その理由をいくつか引用している。
1. Span<T>は意味的に参照と範囲を含む構造体である(ref T data, int length)。実際の実装にかかわらず、こうした構造体への書き込みはアトミックではない。こうした構造体を同時に“引き裂く”と、lengthがデータに一致しなくなる可能性があり、それにより範囲外アクセスや型安全違反が生じ、究極的には“安全”に見えるコードでGCヒープの破壊を引き起こす。
Span<T>の実装には、文字通りそのフィールドにマネージドポインターが含まれることがある。マネージドポインターはヒープオブジェクトのフィールドとしてサポートされておらず、マネージドポインターをGCヒープへの配置を管理するコードは通常、JIT時にクラッシュする。
3. Span<T>は、個別のローカル変数やstackallocされた配列などローカルスタックフレームのデータの参照を許可されている。あるSpan<T>のインスタンスが参照されたデータよりも長く存在していた場合、型安全違反やヒープの破壊など、未定義の振る舞いに繋がる。
ref-like型はいくつかの使用上の制約がある。
- ref-like型は配列の要素の型になれない
- ref-like型はジェネリック型の引数として使用できない
- ref-like変数はボックス化されない
- ref-like型は通常の非ref-like型のフィールドになれない
- 間接的な制約として、ref-like型が非同期メソッドで使用できない;ref-like型のフィールドが許可されていないため
実際には、これはref-like型がパラメーター、ローカル変数、そして値を返すいくつかのケースにおいてのみ利用できる、ということを意味する。あるref-like型は他のref-like型を含むことができる。
全てのref-like方は読み取り専用の構造体でもある(上記を参照)。
参照型と同様に、ref-like型は結局“単一割り当て”となる。提案では安全性を保証する他の方法が記述されているが、これがコンパイラーに最も負荷をかけない方法だ。
C# 8.0 プロトタイプ
C# 8 のための2つの機能がすでにプロトタイプフェーズに達している。
- Null許容参照型: これは参照型をデフォルトで非Null許容にするというものだ。Null許容参照型の変数のためには、Null許容構造体と同様にT?を使用できる。
- デフォルトインターフェイスメソッド: これはC#に制限された形の多重継承を追加するというものだ。
Rate this Article
- Editor Review
- Chief Editor Action