C#14新機能

C#14 新機能 B07_拡張静的プロパティ&メソッド

静的なメンバーも拡張できる

extension ブロックには、これまで見てきたインスタンスメソッドやインスタンスプロパティだけでなく、静的なメソッドや静的なプロパティも書くことができます。今回はその使い方を、Color 構造体を例に見ていきます。

図1: これまでの extension ブロックはインスタンスメソッド/プロパティのみだった(int の IsZero/IsNegative など)

Colorを拡張してアプリ共通の色を定義する

静的な拡張が活躍する場面の一つが、色の定義です。System.Drawing の Color 構造体に対して extension ブロックを書けば、新しい色を作ることも、既存の色に別名を付けることもできます。

例えば、選択行の色として Color.Blue を使うと決めたとします。これをアプリケーション全体で使い回せるように、Color 構造体に SelectedRow という静的プロパティを追加してみます。

図2: Color 構造体に対する extension ブロックを新しく作成する

図3: public static Color SelectedRow => Color.Blue; と定義する

public static class Ex
{
  extension(Color color)
  {
    public static Color SelectedRow => Color.Blue;
  }
}

 

static を付けて書くことで、SelectedRow は Color 構造体そのものに対する静的プロパティになります。SelectedRow の中身を Blue から Green に変えれば、SelectedRow を使っている箇所すべての色が一括で切り替わります。

使う側から見るとColorのプロパティとして見える

使う側のコードでは、Color.SelectedRow と書くだけで選択行の色を取得できます。IntelliSense 上でも、Color 構造体に SelectedRow が新しく追加されたように表示されるので、「選択行の色はこれを使う」と決めておけば、UI 側のコードは常に Color.SelectedRow を参照するだけで済みます。

図4: this.BackColor = Color.SelectedRow; として画面の背景色に適用する

図5: 実行結果。画面の背景色が Color.SelectedRow(Blue)になっている

this.BackColor = Color.SelectedRow;

従来であれば、こうした共通色は専用の定数クラスを作って const で管理する、という方法が一般的でした。しかし静的な拡張プロパティを使えば、「共通の色はどこに書いたか」を探し回る必要がなくなり、色に関する定義はすべて Color 構造体自身に集約できます。

staticを付けない場合との違い

もしこの SelectedRow に static を付けなかった場合は、インスタンスメソッド/プロパティ扱いになるため、使う前に必ずインスタンスを生成(new)する必要があります。わざわざ何も使わないインスタンスを作り、そのインスタンス経由で SelectedRow にアクセスする、という無駄が発生してしまいます。

static を付けておけば、この new が不要になり、Color を直接呼び出すだけで色を選択できます。インスタンスを生成する必要がない場面では、こうした拡張静的プロパティ・拡張静的メソッドを積極的に活用するとよいでしょう。

まとめ

extension ブロックの中に static を付けたメンバーを書けば、拡張対象の型自体に対する静的プロパティ・静的メソッドを追加できます。共通の色や定数のように、インスタンスを必要としない値・処理をまとめたい場合に適した書き方です。

C#14 新機能