[C#]クラス作成時にメソッドチェインを使用する


結論から言うとBuilderパターン

メソッドチェインでつないで一行で設定を入れて、実際にほしいクラスを作成します。MQTTnetとかで使うやつです。
今回はただ一秒ごとにカウントアップするカウンタークラスを作成します。
使うときはこんな感じになります。

        static void Main(string[] args)
        {
            var option = new CounterOptionBuilder().Start(10).Duration(5).End(40).Build();
            var countObject = new Counter(option);
            countObject.Start();
        }

作成するクラスは以下の3つ

  • Counterクラス
    • 実際に使いたいクラス
  • CounterOptrionsクラス
    • Counterクラスに設定する値が入ったクラス
  • CounterOptionBuilderクラス
    • CounterOptionBuilderクラスをメソッドチェインで作成するクラス

サンプルコード

次は実際にほしいクラスです。

    class Counter
    {
        private readonly CounterOptions option;

        public Counter(CounterOptions option)
        {
            this.option = option;
        }

        public void Start()
        {
            var c = option.start;
            while(option.end >= c)
            {
                Console.WriteLine($"counting...{c}");
                Thread.Sleep(1000);
                c += option.duration;
            }
        }
    }

次がBuilderパターンの肝です。
Builderパターンではメソッドは自分を返します。return this;の部分です。
これによってメソッドチェインを実現します。

    class CounterOptionBuilder
    {
        private readonly CounterOptions options = new CounterOptions();
        private int start;
        private int end;
        private int duration;

        public CounterOptionBuilder Start(int value)
        {
            start = value;
            return this;
        }

        public CounterOptionBuilder End(int value)
        {
            end = value;
            return this;
        }

        public CounterOptionBuilder Duration(int value)
        {
            duration = value;
            return this;
        }

        public CounterOptions Build()
        {
            options.start = start;
            options.end = end;
            options.duration = duration;
            return options;
        }
    }

次は設定したい項目をクラス化したものです。Builderパターンでは設定項目をクラスに分離することが多いです。

    class CounterOptions
    {
        public int start { get; set; }
        public int duration { get; set; }
        public int end { get; set; }
    }