以下の内容はhttps://rksoftware.hatenablog.com/entry/2025/11/17/000000より取得しました。


C# 14 を改めて確認しよう! 既存確認コード編 その1

C# 14 を使いたい! そう思っていますね? わかります。私もです。

.NET 10 ももうリリースになります。となれば当然に皆さんお待ちかねの C# 14 を皆が使い始めます。私も使います。

■ 前回までの C# 14

C# 14 の新機能ですが、前回の記事で機能リスト的には Preview 版の時に追いかけていた内容とほぼ同じだとわかりました。
1 項目差がありましたがこれは後日見ていきたいと思います。

rksoftware.hatenablog.com

■ 以前の確認コード

Preview 版の時に追っていたということは、機能確認コードがすでにあるということです。Preview 版の時のコードはまだ動くのか、見てみましょう。
確認コードはこちらです。
github.com

■ ビルドしてみる

当時のコードをなにもせずに、ビルドしてみます。

なんと! エラーが 2 件出ました。逆にエラーが 2 件しか出ませんでした。しかも 2 件は同じ内容で、実質 1 件だけのエラーです。

'Combine': cannot declare instance members in an extension block with an unnamed receiver parameter
'Empty_2': cannot declare instance members in an extension block with an unnamed receiver parameter

エラーが出ているのは 拡張メンバー定義 です。確認コード全体をまずは掲載。
概ね、4 つの確認をしていて、

  • 通常の拡張メンバーの定義
  • 静的メンバーも追加できることの確認
  • ジェネリクス型の確認
  • ジェネリクス型の静的メンバーの確認 です。確認コード全体をまずは掲載。
// 拡張メンバー定義
// 一つのクラスに複数定義可能
public static class SampleExtension
{
    // string に対する拡張メンバー
    // 引数に this  は必要ない
    extension(string s)
    {
        // メンバーのシグニチャに this の引数は不要
        // 一つの extension ブロックの中に複数定義可能
        public bool IsEmpty => (s?.Length ?? 0) == 0;
        public bool IsEmpty_2 => (s?.Length ?? 0) == 0;

        // メソッドも定義可能
        public bool Empty() => (s?.Length ?? 0) == 0;
    }

    // 静的メンバーも定義可能
    extension(string)
    {
        // 静的メソッド
        public string Combine(string first, string second) => first + second;
        // 静的プロパティ
        public string Empty_2 => string.Empty;
    }

    // ジェネリクス型に対する拡張メンバー
    extension<TSource>(IEnumerable<TSource> source)
    {
        public bool IsEmpty => !source.Any();
    }

    // ジェネリクス型に対する拡張メンバー
    extension<TSource>(IEnumerable<TSource>)
    {
        public static IEnumerable<TSource> Combine(IEnumerable<TSource> first, IEnumerable<TSource> second) => Enumerable.Empty<TSource>();
        public static IEnumerable<TSource> Identity => Enumerable.Empty<TSource>();
    }
}

■ どこがエラーになっているか

静的メンバーの追加です。
既存コード

    // 静的メンバーも定義可能
    extension(string)
    {
        // 静的メソッド
        public string Combine(string first, string second) => first + second;
        // 静的プロパティ
        public string Empty_2 => string.Empty;
    }

今回エラーを改修したコード

    // 静的メンバーも定義可能
    extension(string)
    {
        // 静的メソッド
        public static string Combine(string first, string second) => first + second;
        // 静的プロパティ
        public static string Empty_2 => string.Empty;
    }

■ 何が違うか

static キーワードが付いています。これ、ジェネリクスの時は以前からついていましたし、そもそも静的メンバーですし、これでいいのだって感じですね。
もしかしたら、私が間違えていてもともと static 付きが使用だったのかもと思うほどです。

■ 改修コード

改修版のコードは、既存のコードを変えずに別プロジェクトで書いています。

github.com

■ 拡張メンバーは静的メンバーなのか

拡張メンバーはもともと、拡張メンバーを定義しているクラスの静的メンバーでした。つまり、第一引数に拡張対象のインスタンスを自分で渡すことで普通に静的メンバーとして使うことも可能でした。

例えばこんな感じです。

public static class SampleOldExtension
{
    // 第一引数に this を付けることで拡張メソッドとして定義
    public static bool IsEmpty(this int i) => i == 0;
}
Console.WriteLine(SampleOldExtension.IsEmpty(0));
Console.WriteLine(SampleOldExtension.IsEmpty(1));

■ 通常の拡張メンバーを拡張対象のメソッドとして

    extension(string s)
    {
        // メンバーのシグニチャに this の引数は不要
        // 一つの extension ブロックの中に複数定義可能
        public bool IsEmpty => (s?.Length ?? 0) == 0;
        public bool IsEmpty_2 => (s?.Length ?? 0) == 0;

        // メソッドも定義可能
        public bool Empty() => (s?.Length ?? 0) == 0;
    }

インテリセンスで静的メンバーとして出てきませんね。まあそうといえばそうでしょう。

■ 静的拡張メンバー

インテリセンスで静的メンバーとして出てきます。

    // 静的メンバーも定義可能
    extension(string)
    {
        // 静的メソッド
        public static string Combine(string first, string second) => first + second;
        // 静的プロパティ
        public static string Empty_2 => string.Empty;
    }

■ 拡張メンバーの定義クラスの静的メンバーとして

インテリセンスで出てきますね。まあそうといえばそうでしょう。しかしプロパティはだけ注目です。
名前の先頭に get_ が付いています。これは注目ですね。自分で get_ を付けたメソッドを作っていた場合の名前競合でどうなるのか。後日見てい観たいと思います。

■ 次回

次回は、既存の確認コードの確認 その 2。何もしなくてもビルドできるか、ではなく変えるべきところを変えてビルドできるか、を見ていきます。




以上の内容はhttps://rksoftware.hatenablog.com/entry/2025/11/17/000000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14