C#8は今年リリースが予定されており、C#8.xと9のロードマップも形を整えつつあるが、Microsoftは引き続き、次期リリース機能の承認作業を行っている。
Target Typed Expressions
型A、B、およびCがあり、BおよびCがAのサブタイプであるとする。次のようなステートメントを使用すると、コンパイラは、右辺が返す型を判別することができない。
A a1 = b ?? c;
A a2 = x>0 ? b : c;
A a3 = a switch {
B b => b,
C c => c,
_ => throw new System.Exception()
};
通常、これを修正するには、次のようなキャストを追加する必要がある。
A a1 = (A)b ?? (A)c;
A a2 = x>0 ? (A)b : (A)c;
Target-typed switch expression提案では、それぞれのcaseにおいて、式の左辺(A a1
)を使用して、右辺(b ?? c
)が返す型を決定できるようになる。この機能はreturn文( return b ?? c
)でも有効だが、var( var a1 = b ?? c
)には機能しない。
現時点では、このパターンマッチング版(例3)がC#8.0、他の2つが8.xに予定されている。
デコンストラクションでの"default"の許可
この小さな機能では、タプルを初期化するときにキーワードdefaultが使用可能になる。以下は提案からの引用である。
(int i, string s) = default;
(i, s) = default;
廃止(Obsolete)プロパティ
Visual Basicとは異なり、C#では、個々のgetterおよびsetterをobsoleteとマークすることはできず、プロパティ全体のマークのみが可能である。この提案は、そのような状況を改正するものだ。これが重要である理由を理解するために、Cory Nelson氏のコメントを参照してほしい。
私がこれを必要だと感じたのは、ほんの数週間前、プロパティのget/setを多用していたコードを、読み取り専用のctorによる初期化をもっと使用するレコードにクリーンアップしようとしていたときです。
この機能は4月に、C#9からC#8に移動された。
構造体の読み取り専用メンバ
読み取り専用フィールドに割り当てられた場合、またはinパラメーターとして使用された場合、構造体のメソッドにパフォーマンスの小さな問題がある。構造体のメソッドを呼び出すと、コンパイラはまず、防御用のコピーを生成する。通常は問題を引き起こすほど高価ではないが、タイトなループで使用する場合には、わずかながら非効率性が増大する。
構造体が完全に不変(immutable)であれば、構造体全体をreadonlyとしてマークすることで、これを回避できる。しかしながら、パフォーマンス上の理由から、多くの構造体は可変(mutable)である。
読み取り専用インスタンスメソッド{/0}の提案では、開発者が、個々のメソッドを読み取り専用としてマークすることができる。これによって、値が変更されず、防御用コピーが不要であることをコンパイラに教えるのだ。
これがPure属性と違うのは、構造体自体の値を変更しない限りにおいて、読み取り専用メソッドには目に見えるサイドエフェクトが存在する点だ。
自動実装されるプロパティのgetterは、自動的に読み取り専用とみなされる。場合によっては、例えば、プロパティ値が構造体自体に直接保存されるのではなく、ディクショナリに保存されるような場合などは、setterを読み取り専用にマークすることもできる。
現在の提案では、この機能は参照型(クラスとインターフェース)をサポートしない。その理由は3つある。
- パフォーマンス上のメリットがないため。
- readonlyキーワードは、状態が変更されないという意味ではなく、単にオブジェクトのフィールドが直接変更されないという意味であるため。
- この機能は読み取り専用構造体の拡張であり、相当する読み取り専用クラスは存在しないため。