注
この記事は機能仕様です。 仕様は、機能の設計ドキュメントとして機能します。 これには、提案された仕様の変更と、機能の設計と開発時に必要な情報が含まれます。 これらの記事は、提案された仕様の変更が最終決定され、現在の ECMA 仕様に組み込まれるまで公開されます。
機能の仕様と完成した実装の間には、いくつかの違いがある可能性があります。 これらの違いは、関連する 言語設計会議 (LDM) ノートでキャプチャされます。
機能仕様を C# 言語標準に導入するプロセスの詳細については、仕様に関する記事を参照してください。
チャンピオン号: https://github.com/dotnet/csharplang/issues/9058
概要
イベントとコンストラクターのpartial
修飾子で、partial メソッド、partial プロパティ/インデクサーと同様に、宣言部分と実装部分を分離できるようにします。
partial class C
{
partial C(int x, string y);
partial event Action<int, string> MyEvent;
}
partial class C
{
partial C(int x, string y) { }
partial event Action<int, string> MyEvent
{
add { }
remove { }
}
}
モチベーション
C# では、部分メソッド、プロパティ、インデクサーが既にサポートされています。 部分的なイベントとコンストラクターがありません。
部分イベントは、ユーザーが定義 記述できるイベント ライブラリに役立ちます。
partial class C
{
[WeakEvent]
partial event Action<int, string> MyEvent;
void M()
{
RaiseMyEvent(0, "a");
}
}
また、ライブラリで提供されるソース ジェネレーターでは、次の実装が提供されます。
partial class C
{
private readonly WeakEvent _myEvent;
partial event Action<int, string> MyEvent
{
add { _myEvent.Add(value); }
remove { _myEvent.Remove(value); }
}
protected void RaiseMyEvent(int x, string y)
{
_myEvent.Invoke(x, y);
}
}
部分イベントと部分コンストラクターは、ユーザーが部分コンストラクターとイベント定義を記述できる Xamarin のような相互運用コードを生成する場合にも役立ちます。
partial class AVAudioCompressedBuffer : AVAudioBuffer
{
[Export("initWithFormat:packetCapacity:")]
public partial AVAudioCompressedBuffer(AVAudioFormat format, uint packetCapacity);
[Export("create:")]
public partial event EventHandler Created;
}
また、ソース ジェネレーターによってバインディングが生成されます (この場合は Objective-C に対して)。
partial class AVAudioCompressedBuffer : AVAudioBuffer
{
[BindingImpl(BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public partial AVAudioCompressedBuffer(AVAudioFormat format, uint packetCapacity) : base(NSObjectFlag.Empty)
{
// Call Objective-C runtime:
InitializeHandle(
global::ObjCRuntime.NativeHandle_objc_msgSendSuper_NativeHandle_UInt32(
this.SuperHandle,
Selector.GetHandle("initWithFormat:packetCapacity:"),
format.GetNonNullHandle(nameof(format)),
packetCapacity),
"initWithFormat:packetCapacity:");
}
public partial event EventHandler Created
{
add { /* ... */ }
remove { /* ... */ }
}
}
詳細な設計
全般
イベント宣言構文 (§15.8.1) が拡張され、 partial
修飾子が許可されます。
event_declaration
- : attributes? event_modifier* 'event' type variable_declarators ';'
+ : attributes? event_modifier* 'partial'? 'event' type variable_declarators ';'
- | attributes? event_modifier* 'event' type member_name
+ | attributes? event_modifier* 'partial'? 'event' type member_name
'{' event_accessor_declarations '}'
;
インスタンス コンストラクター宣言構文 (§15.11.1) が拡張され、 partial
修飾子が許可されます。
constructor_declaration
- : attributes? constructor_modifier* constructor_declarator constructor_body
+ : attributes? constructor_modifier* 'partial'? constructor_declarator constructor_body
;
a の提案があり最後の修飾子 (メソッド、プロパティ、および型宣言の場合) としてだけでなく、修飾子間の任意の場所でpartial
修飾子を許可します。
partial
修飾子を持つイベント宣言は、partial イベント宣言と言われ指定された名前を持つ 1 つ以上のpartial イベントに関連付けられます (アクセサーのない 1 つのイベント宣言で複数のイベントを定義できることに注意してください)。
partial
修飾子を持つコンストラクター宣言は、partial コンストラクター宣言と言われ指定されたシグネチャを持つpartial コンストラクターに関連付けられます。
部分的なイベント宣言は、実装宣言と言われますevent_accessor_declarations
を指定するか、extern
修飾子を持つ場合です。
それ以外の場合は、 定義宣言。
部分コンストラクター宣言は、セミコロン本体を持ち、修飾子がない場合extern
定義宣言と呼ばれています。
それ以外の場合は、宣言 を実装するです。
partial class C
{
// defining declarations
partial C();
partial C(int x);
partial event Action E, F;
// implementing declarations
partial C() { }
partial C(int x) { }
partial event Action E { add { } remove { } }
partial event Action F { add { } remove { } }
}
部分メンバーの定義宣言のみが参照に参加し、使用サイトおよびメタデータの出力と見なされます。 (詳細な コメントを除く)。実装宣言シグネチャは、関連付けられた本体の null 許容分析に使用されます。
部分的なイベントまたはコンストラクター:
- 部分型のメンバーとしてのみ宣言できます。
- 1 つの定義と 1 つの実装宣言が必要です。
-
abstract
修飾子は使用できません。 - インターフェイス メンバーを明示的に実装できません。
部分イベントがフィールドに似ていません (§15.8.2)。
- コンパイラによって生成されたバッキング ストレージまたはアクセサーはありません。
-
+=
および-=
操作でのみ使用でき、値として使用することはできません。
定義する部分コンストラクター宣言にコンストラクター初期化子 (: this()
または : base()
; を含めることはできません §15.11.2)。
解析の中断
より多くのコンテキストで partial
修飾子を許可することは、重大な変更です。
class C
{
partial F() => new partial(); // previously a method, now a constructor
@partial F() => new partial(); // workaround to keep it a method
}
class partial { }
言語パーサーを簡略化するために、 partial
修飾子は、上記で文法の変更を明示的に指定しない場合でも、メソッドに似た宣言 (ローカル関数や最上位レベルのスクリプト メソッドなど) でも受け入れられます。
属性
結果のイベントまたはコンストラクターの属性は、対応する位置にある部分宣言の結合属性です。 結合された属性は指定されていない順序で連結され、重複は削除されません。
部分イベント宣言では、method
attribute_target (§22.3) は無視されます。
アクセサー属性は、アクセサー宣言からのみ使用されます (実装宣言の下にのみ存在できます)。
param
とreturn
attribute_targetは、すべてのイベント宣言で既に無視されることに注意してください。
実装宣言の呼び出し元情報属性は、セクション Caller-info 属性 の部分プロパティ提案で指定されているようにコンパイラによって無視されます (部分イベントとコンストラクターを含むすべての部分 メンバー に適用されます)。
署名
部分メンバーの両方の宣言には、部分プロパティと同一致するシグネチャが必要です
- 型と ref の種類の違いは、ランタイムにとって重要な部分宣言の場合、コンパイル時エラーが発生します。
- 部分宣言間のタプル要素名の違いにより、コンパイル時エラーが発生します。
- 宣言は同じ修飾子を持つ必要がありますが、修飾子は異なる順序で表示される場合があります。
- 例外: これは、実装宣言にのみ表示される
extern
修飾子には適用されません。
- 例外: これは、実装宣言にのみ表示される
- 部分宣言のシグネチャに構文上の違いがある場合、コンパイル時の警告が発生しますが、次の例外があります。
- 属性リストは、 aboveの説明に従って一致する必要はありません。
- Null 許容コンテキストの違い (不注意や注釈付きなど) では、警告は発生しません。
- 既定のパラメーター値は一致する必要はありませんが、実装するコンストラクター宣言に既定のパラメーター値がある場合は警告が報告されます (定義宣言のみが参照に含まれるため、これらは無視されるため)。
- パラメーター名がコンストラクター宣言の定義と実装によって異なる場合、警告が発生します。
- null 許容の違いは null 許容未指定を伴わないため、警告が発生します。
ドキュメントのコメント
定義宣言と実装宣言の両方にドキュメント コメントを含めることができます。 ドキュメント コメントは、イベント アクセサーではサポートされないことに注意してください。
部分メンバーのいずれかの宣言にのみドキュメント コメントが存在する場合、それらのドキュメント コメントは通常どおりに使用されます (ドキュメント XML ファイルに出力される Roslyn API を介して表示されます)。
部分メンバーの両方の宣言にドキュメント コメントが存在する場合、定義する宣言のすべてのドキュメント コメントが削除され、実装する宣言のドキュメント コメントのみが使用されます。
部分メンバーの宣言間でパラメーター名が異なる場合、 paramref
要素は、ソース コードのドキュメント コメントに関連付けられている宣言のパラメーター名を使用します。
たとえば、実装宣言に配置されたドキュメント コメントの paramref
は、そのパラメーター名を使用して実装宣言のパラメーター シンボルを参照します。
メタデータシグネチャは定義宣言のパラメーター名を使用するため、混乱を招く可能性があります。
この混乱を避けるために、パラメーター名が部分メンバーの宣言全体で一致することを確認することをお勧めします。
未解決の質問
メンバーの種類
部分イベント、コンストラクター、演算子、フィールドが必要ですか? 最初の 2 つのメンバーの種類を提案しますが、他のサブセットも考慮できます。
部分 primary コンストラクターも考慮できます。たとえば、ユーザーが複数の部分型宣言で同じパラメーター リストを持つことが許可されます。
属性の場所
部分イベントの [method:]
属性ターゲット指定子 (または定義宣言のみ) を認識する必要がありますか?
その後、結果として得られるアクセサー属性は、両方の (または定義する) 宣言部分の method
ターゲット属性と、実装宣言のアクセサーからの自己ターゲット属性と method
ターゲット属性の連結になります。
さまざまな宣言の種類の属性を組み合わせることは前例のないものであり、Roslyn での属性照合の現在の実装ではサポートされていません。
また、部分的なイベントだけでなく、すべてのフィールドに似たイベントや外部イベントだけでなく、 [param:]
と [return:]
を認識することも検討できます。
詳細については、「https://github.com/dotnet/roslyn/issues/77254」を参照してください。
C# feature specifications