C#でnull許容型にNonZeroを拡張メソッドで実装する

rubyではこんなことができる。

3.nonzero?  # => 3
0.nonzero?  # => nil


ゼロならnil、非ゼロならもとの値が返る。
これと似たようなことをC#でやりたい。

int? hoge = 3;
hoge.NonZeroValue();  // => 3

int? piyo = 0;
piyo.NonZeroValue();  // => null


もとがnullならnullが返るようにする。

int? fuga = null;
fuga.NonZeroValue();  // => null

という拡張メソッドを作る。



以下実装。
  public static class NumericExtension
  {
    public static bool IsZero<T>(this T self)
      where T : struct, IComparable<T>
    {
      return self.CompareTo(new T()) == 0;
    }

    public static T? ZeroValue<T>(this T? self)
      where T : struct, IComparable<T>
    {
      return self.HasValue && self.Value.IsZero() ? self : null;
    }
  }


ジェネリック制約で値型かつIComparable<T>インターフェースつきのものに限定する。
これで数値はまとめてカバーできる。




ゼロ値判定は、ジェネリック型では==演算子が使えないのでCompareToする。

値型を引数なしでnewすると、既定値のインスタンスが取れる。
数値では、既定値がどれもゼロなのでこれと比較すればよい。

値型の既定値。


これで、ゼロpresence的な書き方ができるようになった。

同様に、正数、負数、非正数(ゼロまたは負数)、非負数(ゼロまたは正数)バージョンも作れる。


世の中には、ゼロや負数を無効な値として使っているものがある。
しかし、無効値は無効値らしくnullにしたい。

ゼロはゼロ、無効はnull。
ゼロは無効でもnullでもない。


無効値が無効値らしくないサービスやライブラリと連携するときに、いちいちゼロ値判定するのは冗長。
というわけで、無効値をメソッド一発でnull化できるようにした。


それにしてもrubyのnonzero?メソッド、boolean返さないのに「?」がついてるのが気持ち悪い・・・。

2013年9月

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

アーカイブ