今回はイベントにおけるpartialの使い方を扱います。イベントについても、これまでは自動生成側に幽霊コードとして実装を書くことができていました。C# 14からは、定義パーツを使った「契約による実装」がイベントでもできるようになりました。考え方はこれまで扱ってきたコンストラクターの場合と同じです。
自動生成側にイベントを実装する
まずは自動生成側(Form1.Designer.cs)にイベントを作成します。バッキングフィールドとして private event Action _myClick を用意し、公開用の public event Action MyClick を add/remove アクセサー付きで定義します。
自動生成側(Form1.Designer.cs)に_myClickとMyClickイベントを定義
add/remove の中には、それぞれ何かしらのロジックがある想定で、Debug.WriteLine による出力処理を追加しています。
add/removeそれぞれにDebug.WriteLineでのログ出力ロジックを追加
private event Action _myClick;
public event Action MyClick
{
add
{
System.Diagnostics.Debug.WriteLine("addddd");
_myClick += value;
}
remove
{
System.Diagnostics.Debug.WriteLine("removeeeeeeeee");
_myClick -= value;
}
}
この状態のままだと、これまでと同じく手書き側からは存在に気づけない「幽霊コード」になってしまいます。そこでMyClickにpartialを付けます。
partialを付けると定義パーツが必要になる
public event Action MyClick の頭にpartialを付けると、MyClickの箇所に赤い波線が表示され、「CS9276: 部分的メンバー ‘Form1.MyClick’ には定義パーツが必要です。」というエラーが出るようになります。これによって、手書き側で対応する定義を書かなければならないことが強制されます。
partialを付けるとCS9276エラーが表示され、定義パーツが必要になる
手書き側で定義パーツを実装する
手書き想定側(Form1.cs)に、同じ型でイベントを宣言します。public partial event Action MyClick; と書くだけでOKです。
手書き側(Form1.cs)にpublic partial event Action MyClick;を宣言
public partial class Form1 : Form
{
public partial event Action MyClick;
public Form1()
{
InitializeComponent();
}
}
これでエラーが解消され、「問題は見つかりませんでした」の表示に変わります。手書き側からもMyClickというイベントが存在することを認識しながら実装できるようになりました。
定義パーツを書いたことでエラーが解消される
partialを付けない場合との違い
これまでもpartialを付けなければ、自動生成側だけにイベントを実装することができていました。ただしこの場合、手書き側からはそのイベントの存在を知る手段がなく、幽霊コードのままになってしまいます。試しに手書き側の定義(public partial event Action MyClick;)をコメントアウトすると、自動生成側で再びエラーが発生することが確認できます。
手書き側の定義パーツをコメントアウトすると再びエラーになる
partialを付けてイベントを定義することで、「定義パーツが必要です」というコンパイラのメッセージを通じて手書き側もそのイベントの存在に気づき、意識しながら実装できる環境になった、というのが今回のポイントです。
Udemyでの動画版はこちらからご覧いただけます
00_はじめに
01_VisualStudio2026をインストールしてください
A01_fieldキーワード
B01_extensionブロックとは
B02_拡張メソッドとは
B03_extensionブロック
B04_型パラメータありの拡張メソッド
B05_型パラメータありのextensionブロックの書き方
B06_拡張プロパティ
B07_拡張静的プロパティ&メソッド
B08_拡張演算子
C01_partialコンストラクター
C02_幽霊コードを定義パーツで契約による実装をするという考え方
C03_partialイベント
D01_Null条件付き代入
E01_複合代入演算子のオーバーロード
F01_明示的な型を指定せずにラムダパラメータでパラメータ修飾子を使用する
G01_nameofはバインドされていないジェネリック型をサポートします
H01_SpanTおよびReadOnlySpanTのより暗黙的な変換
Udemyでの動画版はこちらからご覧いただけます