Option的なものを作ろうとして絶望した

ものすごい久々にブログを書くのですが、あまり役に立たない情報です(汗

ここ半年ほど C# を使用するプロジェクトに携わっています。C# は 4.0 から?だと思うのですが、ジェネリクスの型パラメータに変位指定(in とか out とか)ができるようになっています。
共変が 、反変が と、型パラメータを使用できる場所が分かりやすい指定になっています(out = 戻り値の型として使用可能、in = 仮引数の型として使用可能)。
また、いつのころからか導入されていた LINQ もあるのでリスト操作を非常にやりやすくなっています。しかも基本的に遅延リスト(というか、IEnumerable といイテレータを取得可能なインタフェース)なのも、慣れると嬉しいです。

しかしながら、LINQ を使っていればいるほど、SelectMany(Scala でいうところの flatMap) を使っていればいるほど、Scala でいうところの Option が無いのが耐え難いです。Option が無いために、以下のようなコードを頻繁に書いています。

entities.Select(x => x.Foo).Where(x => x != null).Select(x => x.Bar);


ちがうっ!ちがうんだ!!null 値かどうかに着目したいんじゃないです!!


Foo プロパティの先の Bar プロパティの値を取得したいだけなのですが、プロパティの設定有無をチェックするために null かどうかを調べる必要があります。
もし、Option 型があれば Foo プロパティの型自体を Option[Foo] にすることや、あるいは null の場合は None を返すような ToOption 拡張メソッドを用意することで、よりシンプルに記述できます。以下のような感じです。

entities.SelectMany(x => x.Foo.ToOption().Select(y => y.Bar));


そして、つい先日ついに我慢できなくなり、Scala の Option 的なものを作ろうとしたのですが・・・

public interface IOption<out T> : IEnumerable<T>
{
}
public struct Some<T> : IOption<T>
{
  // 省略
}
public struct None<T> : IOption<T>
{
  // 省略
}

↑ここまでは問題ありませんでした。
ところで、C#LINQ には、SingleOrDefault というメソッドがあります。このメソッドは、要素が 1 件あればそれを、0 件ならデフォルト値を返すという振る舞いをします。しかし、デフォルト値は default(T) ときまっており、利用時に指定できません。この振る舞いが以外不便で、利用時に指定したかったので、IOption に GetOrElse を実装しようとしたのですが・・・

public interface IOption<out T> : IEnumerable<T>
{
  T GetOrElse(T value); // コンパイルエラー
}

T は として宣言しているため、メソッドの引数として使用することは出来ません。でも、出来ることならば共変としておきたいので、Scala のようにメソッドに型変数を追加して、下限境界を指定すればいいやと思いました。
Scala だったら以下みたいな感じです。

  def getOrElse[U>:T](value: U): U

・・・・・・・・C# では下限境界の指定が出来ない模様です orz
C# も 4.0 になって out とか in とか書けるのだから [U>:T] みたいな下限境界も指定できるだろうとおもっていたのですが、見つけられませんでした。C# で型パラメータに対する制約は where で書くのですが、書けるのは以下の 4 種類くらいなもので下限境界を指定する方法がありませんでした。

where T : <実際の型>
where T : U
where T : struct // 値型
where T : class // 参照型

というわけで、Option 的なものはいまだ作らず、where(x => x != null) と書いています orz