メソッドチェーンとは

メソッドチェーン(Method Chain)とは、オブジェクト指向プログラミングにおいて、

複数のメソッドを一連の操作として連続で呼び出すテクニックです。

メソッドを連結して使うことで、コードを簡潔にし、直感的に扱いやすくなります。

メソッドチェーンの例

Unityでは、StringBuilderLINQを使ってメソッドチェーンを使用することがよくあります。

LINQでは、複数の人物コレクションから以下のような流れでデータを取得できます。

  • 年齢が20歳以上の人物を抽出
  • 名前順に並び替え
  • 名前の一覧を取得

この流れを、以下のように記述することができます。

var result = people.Where(p => p.Age > 20)
                   .OrderBy(p => p.Name)
                   .Select(p => p.Name);

StringBuilderでも以下の様にメソッドチェーンで処理を呼び、

文字列を連結することが出来ます。

StringBuilder builer = new StringBuilder();
builder.AppendLine("private void Sample()")
			 .AppendLine("{")
		   .AppendLine("     int hoge;")
	 		 .AppendLine("}")

メソッドチェーンのメリット

簡潔さ

前段のサンプルのように、複数の処理を少ない行数で表現できるため、コードがシンプルになります。

処理の流れが明確になる

前段のサンプルコードのように、処理のステップが順番に並ぶため、コードの流れがわかりやすくなります。

データの加工、フィルタリング、並び替えといったステップが視覚的に把握しやすくなります。

イミュータブルなデータの操作に向いている

LINQのメソッドチェーンでは、元のコレクションを変更することなく、新しい結果を返します。

メソッドチェーンのデメリット

デバッグが難しくなる

メソッドチェーンを長くすると、途中でエラーが発生した場合にどの段階で問題が起こっているのか特定するのが難しくなります。

特に例外が発生した場合、問題が発生した箇所を把握しにくく、デバッグが複雑になるかもしれません。

可読性が下がることもある

多くのメソッドを連続で使用すると、処理の内容を一目で把握しづらくなり、

その結果、保守が難しくなる可能性があります。

パフォーマンスに影響を与える場合がある

簡潔に記述できる反面、あまり多用するとオブジェクトが頻繁に生成されることがあります。

特に大量のデータを扱う場合、不必要なオブジェクトが生成され、メモリやパフォーマンスに悪影響を与える可能性があります。

null例外

メソッドチェーンの途中でオブジェクトがnullになると、例外が発生しやすくなります。

C# 8.0以降で使用できる「null条件演算子」(?.)を使うことで回避できる場合もありますが、

メソッドチェーン全体でnullを適切に扱わないと、予期しないエラーの原因となることがあります。

メソッドチェーン用クラスを作ってみる

音源を再生するAudioSourceメソッドチェーンで呼び出すコンポーネントを実際に作ってみました。

各メソッドがthisを返しています。

using UnityEngine;

public class AudioPlayer : MonoBehaviour
{
    [SerializeField] private AudioSource _source;
    
    #if UNITY_EDITOR
    private void Reset()
    {
        TryGetComponent(out _source);
    }
    #endif
    
    public AudioPlayer Play()
    {
        _source.Play();
        return this;
    }
    
    public AudioPlayer Stop()
    {
        _source.Stop();
        return this;
    }
    
    public AudioPlayer Pause()
    {
        _source.Pause();
        return this;
    }
    
    public AudioPlayer SetVolume(float volume)
    {
        _source.volume = volume;
        return this;
    }
    
    public AudioPlayer SetPitch(float pitch)
    {
        _source.pitch = pitch;
        return this;
    }
    
    public AudioPlayer SetLoop(bool loop)
    {
        _source.loop = loop;
        return this;
    }
    
    public AudioPlayer SetClip(AudioClip clip)
    {
        _source.clip = clip;
        return this;
    }
}

これを以下の様に呼び出すと、

ピッチと音量を変更しループにした状態で再生されます。

LINQStringBuilderのサンプルのようにメソッドをつなげて呼び出せるのが分かると思います。

[SerializeField] private AudioPlayer _audioPlayer;

private void Start()
{
    _audioPlayer
        .SetLoop(true)
        .SetPitch(1.0f)
        .SetVolume(0.5f)
        .Play();
}

まとめ

今回はメソッドチェーンについて解説しました。 C#のメソッドチェーンは、データの加工やフィルタリング、シンプルな処理の組み合わせに非常に有用ですが、 デバッグのしやすさやパフォーマンスに対しては注意が必要です。

メソッドチェーンが長くなりすぎたり、複雑なロジックを含む場合には、 適度に分解して可読性や保守性を保つことが重要です。

🔗関連ページ