ターゲット型のnew
式
手記
この記事は機能仕様です。 仕様は、機能の設計ドキュメントとして機能します。 これには、提案された仕様の変更と、機能の設計と開発時に必要な情報が含まれます。 これらの記事は、提案された仕様の変更が最終決定され、現在の ECMA 仕様に組み込まれるまで公開されます。
機能の仕様と完成した実装の間には、いくつかの違いがある可能性があります。 これらの違いは、関連する 言語設計会議 (LDM) ノートでキャプチャされます。
機能仕様を C# 言語標準に導入するプロセスの詳細については、仕様に関する記事を参照してください。
チャンピオンの課題: https://github.com/dotnet/csharplang/issues/100
概要
型がわかっている場合は、コンストラクターの型指定を必要としません。
モチベーション
型を複製せずにフィールドの初期化を許可します。
Dictionary<string, List<int>> field = new() {
{ "item1", new() { 1, 2, 3 } }
};
使用法から推論できる場合は、型の省略を許可します。
XmlReader.Create(reader, new() { IgnoreWhitespace = true });
型をスペル アウトせずにオブジェクトをインスタンス化します。
private readonly static object s_syncObj = new();
仕様
target_typed_new が object_creation_expression の新しい構文形式として受け入れられ、この中で 型 は省略可能です。
object_creation_expression
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer
| target_typed_new
;
target_typed_new
: 'new' '(' argument_list? ')' object_or_collection_initializer?
;
target_typed_new 式には型がありません。 ただし、新しい オブジェクト作成変換 は、式からの暗黙的な変換であり、target_typed_new からすべての型に存在します。
ターゲット型 T
が与えられると、T
が System.Nullable
のインスタンスである場合、T0
は T
の基になる型です。 それ以外の場合、T0
は T
です。 型 T
に変換される target_typed_new 式の意味は、型として T0
を指定する対応する object_creation_expression の意味と同じです。
target_typed_new が単項演算子または二項演算子のオペランドとして使用されている場合、または オブジェクト作成変換の対象にならない場合は、コンパイル時エラーです。
未解決の問題: デリゲートとタプルをターゲット型として許可すべきでしょうか?
上記の規則には、デリゲート (参照型) とタプル (構造体型) が含まれます。 どちらの型も構築可能ですが、型が推論可能な場合は、匿名関数またはタプル リテラルを既に使用できます。
(int a, int b) t = new(1, 2); // "new" is redundant
Action a = new(() => {}); // "new" is redundant
(int a, int b) t = new(); // OK; same as (0, 0)
Action a = new(); // no constructor found
その他
仕様の結果を次に示します。
throw new()
が許可されている (ターゲットの型がSystem.Exception
)- ターゲット型の
new
は、二項演算子では使用できません。 - 対象となる型が指定されていない場合、単項演算子、
foreach
のコレクション、using
内、分解中、await
式内、匿名型プロパティ (new { Prop = new() }
) として、lock
ステートメント内、sizeof
内、fixed
ステートメント内、メンバー アクセス中 (new().field
)、動的ディスパッチ操作中 (someDynamic.Method(new())
)、LINQ クエリ内、is
演算子のオペランドとして、??
演算子の左オペランドとして、などの使用は許可されません。 - また、
ref
として許可されていません. - 次の種類の型は、変換のターゲットとして許可されません
- 列挙型:
new()
は機能します (既定値を指定new Enum()
動作するため)、列挙型にはコンストラクターがないため、new(1)
は機能しません。 - インターフェイス型: これは、COM 型の対応する作成式と同じように動作します。
- 配列型: 配列には、長さを指定するための特別な構文が必要です。
- 動的:
new dynamic()
を許可しないため、ターゲット型としてdynamic
を使用したnew()
は許可されません。 - タプル: 基になる型を使用したオブジェクトの作成と同じ意味を持ちます。
- object_creation_expression で許可されていない他のすべての型も、たとえばポインター型から除外されます。
- 列挙型:
欠点
ターゲット型の new
によって破壊的変更の新しいカテゴリが作成されるという懸念がありましたが、null
と default
では既に問題が発生しており、大きな問題ではありません。
選択肢
フィールドの初期化で型が長すぎて重複できないという苦情のほとんどは、型引数 型自体ではなく についてです。new Dictionary(...)
(または類似) のような型引数のみを推論し、引数またはコレクション初期化子からローカルで型引数を推論できます。
質問
- 式ツリーでの使用を禁止する必要がありますか? (いいえ)
- この機能は
dynamic
引数とどのように対話しますか? (特別扱いなし) new()
での IntelliSense の動作方法はどうあるべきか (単一のターゲット型がある場合のみ)
デザインミーティング
C# feature specifications