systembankスタッフのブログ

システムバンクスタッフのブログです。

NULLの判定 その2

値を持っているか確認するプロパティの追加

JavaのOptionalに実装されているisPresent()に相当する機能を実装します。

C#にはプロパティがあるので値を保持しているか判定するプロパティを追加します。

また、C#にはnull非許容型クラスのコンテナ「Nullable<T>」クラスがあり、このクラスにHasValueプロパティがあるのでこちらに倣って追加します。

      public bool HasValue
        {
            get { return value != null; }
        }

C#7.0ではもう少し簡潔にかけるのでこうなります。

        public bool HasValue => value != null;

値がある場合の処理を記述するメソッドを追加

同じくifPresent(Consumer<? super T> consumer)に相当する機能を実装します。

ConsumerはC#のActionに相当するので引数を変更して追加します。

        public void IfPresent(Action<T> action)
        {
            if (value != null)
            {
                action(value);
            }
        }

これで値がnull以外のときのみactionで指定した処理が実行され、それ以外は何もしないようにできました。

今のところでの使い方はざっくり下記のようになります。

    class Program
    {
        static void Main(string[] args)
        {
            var argsOpt = new Optional<string[]>(args);
            DoSomething(GetSomething(argsOpt));
        }

        private static void DoSomething(Optional<string> opt)
        {
            opt.IfPresent(s => Console.WriteLine("{0}ですよ。", s));

            if (!opt.HasValue)
            {
                Console.WriteLine("nullですよ。");
            }
        }

        private static Optional<string> GetSomething(Optional<string[]> argsOpt)
        {
            string s = null;
            argsOpt.IfPresent(args => s = string.Join(",", args));

            return new Optional<string>(s);
        }
    }

値が無い場合のメソッドも追加

DoSomethingメソッド内でHasValueを使っているということは値を扱う側でNULL判定をしていると同義なのでメソッドを追加します。

Javaのドキュメントを見たけどこのメソッドが無いような。見間違いだったら済みません。

    public void IfNotPresent(Action action)
        {
            if (value == null)
            {
                action();
            }
        }

これを使ってサンプルを書き換えるとDoSomethingメソッドはこうなります。

        private static void DoSomething(Optional<string> opt)
        {
            opt.IfPresent(s => Console.WriteLine("{0}ですよ。", s));
            opt.IfNotPresent(() => Console.WriteLine("nullですよ。"));
        }

生成メソッドの追加

コンストラクタをそのまま使っているとGeneric引数を記述するのがメンドイのでクラスとメソッドを追加します。

    static class Optional
    {
        public static Optional OfNullable(T value)
           where T : class
        {
            return new Optional(value);
        }
    }

これを使ってサンプルプログラムを書き換えます。

    class Program
    {
        static void Main(string[] args)
        {
            var argsOpt = Optional.OfNullable(args);
            DoSomething(GetSomething(argsOpt));
        }

        private static void DoSomething(Optional opt)
        {
            opt.IfPresent(s => Console.WriteLine("{0}ですよ。", s));
            opt.IfNotPresent(() => Console.WriteLine("nullですよ。"));
        }

        private static Optional<string> GetSomething(Optional<string[]> argsOpt)
        {
            string s = null;
            argsOpt.IfPresent(args => s = string.Join(",", args));

            return Optional.OfNullable(s);
        }
    }
    class Optiona<T>
        where T : class
    {
        private T value;

        public Optional(T value)
        {
            this.value = value;
        }

        public bool HasValue => value != null;

        public void IfPresent(Action<T> action)
        {
            if (value != null)
            {
                action(value);
            }
        }

        public void IfNotPresent(Action action)
        {
            if (value == null)
            {
                action();
            }
        }
    }

    static class Optional
    {
        public static Optional<T> OfNullable<T>(T value)
           where T : class
        {
            return new Optional<T>(value);
        }
    }
    

これで利用側プログラムからNULLを判定する部分が消えすっきりしたプログラムに変わったと思います。

次回

JavaのOptionalにはまだいろいろメソッドがあるのでそれを実装してみます。