PR

[C#]拡張メソッドとは?作成方法と使い方

今回は拡張メソッドについてです。
この記事では拡張メソッドでどんなことが出来るのか、使い方や作成方法を紹介します。

スポンサーリンク

拡張メソッドとは?

拡張メソッドとは、既存の型(クラスやインターフェース)を変更することなくメソッドを追加することができる機能です。自分以外の人が書いたクラスやインターフェースに手軽にメソッドを追加することができます。LINQもこの拡張メソッドを使ってコレクションに機能を追加しています。
追加した拡張メソッドは追加した型のインスタンスメソッドとして呼び出すことができるようになります。詳しくは後述で。

スポンサーリンク

拡張メソッドの作成方法と使い方

拡張メソッドは静的クラス(static class)内に定義する必要があります。
特徴的なのが第1引数です。thisを付け、後ろに拡張対象の型名、そしてその型のインスタンスを格納する引数名を指定します。その引数を使い拡張メソッド内で拡張元のメンバーにアクセスすることができます(プライベートメンバーはアクセスできない)。

public static class クラス名
{
    public static 拡張メソッドの戻り値の型 拡張メソッド名(this 拡張対象の型名 引数名) { ... }
}

サンプルです。

using System;
class Program {
    static void Main(){
        //SampleClassのインスタンスを作成
        SampleClass cls = new SampleClass();

        //拡張メソッドを呼び出す
        string ret = cls.MethodEx()

        //結果を表示
        Console.WriteLine(ret);
    }
}

//拡張されちゃうクラス
class SampleClass {
    public string Field = "拡張元のフィールド";
}

//SampleClass拡張用のクラス
static class SampleClassExtensions {
    //拡張メソッドの定義
    public static string MethodEx(this SampleClass cls)
    {
        return $"拡張メソッドが呼ばれました。{cls.Field}も使えるよ。";
    }
}
拡張メソッドが呼ばれました。拡張元のフィールドも使えるよ。

引数のある拡張メソッドを作成したい場合は、thisの付いた引数の後ろに「型名 引数名」をカンマで区切って指定します。

using System;
class Program {
    static void Main(){
        //SampleClassのインスタンスを作成
        SampleClass cls = new SampleClass();

        //拡張メソッドを呼び出す
        string ret = cls.MethodEx(10, 20);

        //結果を表示
        Console.WriteLine(ret);
    }
}

//拡張されちゃうクラス
class SampleClass { }

//SampleClass拡張用のクラス
static class SampleClassExtensions {
    //拡張メソッドの定義
    public static string MethodEx(this SampleClass cls, int x, int y)
    {
        return $"拡張メソッドが呼ばれました。x={x}, y={y}";
    }
}
拡張メソッドが呼ばれました。x=10, y=20
スポンサーリンク

同じ名前のメソッドがすでにあったら?

拡張元の型に同じ名前のメソッドがすでにあった場合は、元からあるメソッドが優先されます。

using System;
class Program {
    static void Main(){
        //SampleClassのインスタンスを作成
        SampleClass cls = new SampleClass();

        //結果を表示
        Console.WriteLine(cls.MethodEx());
    }
}

//拡張元になるクラス
class SampleClass {
    public string MethodEx() => "元のクラスにあるメソッドです。";
}

//SampleClass拡張用のクラス
static class SampleClassExtensions {

    //同じ名前で拡張メソッドを定義したら?
    public static string MethodEx(this SampleClass cls) => "拡張メソッドです。";
}
元のクラスにあるメソッドです。
スポンサーリンク

.NET APIに拡張メソッドを追加してみる

.NET APIはマイクロソフトが用意している部品群(クラス)のことです(intとかstringとかいろいろ)。stringクラスに拡張クラスを追加してみます。

using System;
class Program {
    static void Main(){
        //stringに追加した拡張メソッドを実行してみる
        var str = "あいうえお";
        Console.WriteLine(str);
        Console.WriteLine(str.insertSpace());

        //こうしても呼べる
        Console.WriteLine("abcde".insertSpace());
    }
}

static class stringExtensions {
    //文字と文字の間にスペースを入れるメソッド
    public static string insertSpace(this string s) => String.Join(" ", s.Select(c => c));
}
あいうえお
あ い う え お
a b c d e

あと自分的によく使うのは、LINQ(IEnumerableインターフェース)に拡張メソッドを追加したりします。foreachで要素と一緒にインデックスが欲しいというのがよくあるので、それ用のメソッドを追加しています。ジェネリックでいろんな型で使えるので便利です。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main() {
        var list = new List<string> { "aaa", "bbb", "ccc", "ddd" };
        foreach ((var i, var s) in list.Enumerate()) {
            Console.WriteLine($"{i}:{s}");
        }
    }
}

static class LinqExtensions {
    //インデックスと要素の入ったタプルを返すメソッド
    public static IEnumerable<(int, T)> Enumerate<T>(this IEnumerable<T> source)
    {
        return source.Select((element, index) => (index, element));
    }
}
0:aaa
1:bbb
2:ccc
3:ddd

と、こんな感じで拡張メソッドを使うと既存のクラスなどにちょっと機能を追加するというのが簡単にできるので覚えて損はないはずです。
以上


C# 記事まとめページに戻る(他のサンプルコードもこちら)

C# プログラミング講座
C#についての記事まとめページです。開発環境VisualStudioのインストール方法や使い方、プログラミングの基礎知識についてや用語説明の記事一覧になっています。講座の記事にはすぐに実行できるようにサンプルコードを載せています。

コメント