.NETには、参照と値(int、double、struct、enumなど)の2つのタイプのカテゴリがあります。それらの違いの中には、参照が可能になるのnull
に対し、値は不可能であるという事実があります。したがって、値の型があり、「オプション」または「不明」のセマンティクスを伝えたい場合は、で装飾できますNullable<>
。Nullable<>
は型によって制約され、値型のみを受け入れることに注意してください(where T : struct
句があります)。Nullable<>
コンパイラからの特別なアフォーダンスもあり、それによりnull
値が以下から保護されNullReferenceExceptions
ます。
string x = null;
x.ToString(); // throws a NullReferenceException
int? y = null;
y.ToString(); // returns ""
関数型言語(Scala、F#、Haskell、Swiftなど)では、存在null
しないことが一般的です。これは、人々の存在を全体null
として悪い考えだと考えており、言語設計者はそれを拒否することでこの問題に取り組むことを決めたからです。
これは、これらの言語で非価値を表す何らかの方法が再び必要であることを意味します。Option
タイプを入力します(命名法は異なり、Maybe
Haskellで呼び出されます)。これはNullable
、値が「なし」または「不明」などのケースを追加するために型をラップするという点で、同様のジョブを実行します。
本当の違いは、実装する言語によって提供される追加機能にありますOption
。例として、Option.map
(擬似コードで)以下を取ります:
function Option<T2> Option.map(opt: Option<T1>, mapFunc: T1 -> T2) {
if (opt is None) return None
else return Option<T2>(mapFunc(opt.Value))
}
次のような関数の連鎖Option.map
は、C#の至る所に見られる典型的なnullチェックボイラープレートを回避する強力な方法です。
if (service == null)
return null;
var x = service.GetValue();
if (x == null || x.Property == null)
return null;
return x.Property.Value;
C#でNullableに相当するものは次のとおりです。
public static Nullable<T2> Map<T1, T2>(this Nullable<T1> nullable, Func<T1, T2> f)
where T1 : struct
where T2 : struct
{
if (!nullable.HasValue) return (T2?)null;
else return (T2?) f(nullable.Value);
}
ただし、これは値型に対してのみ機能するため、C#のユーティリティは限られています。
C#の新しいバージョンは、メソッドとプロパティアクセサーのみに適用されることを除いて?.
、Option.map
関数に似ている「null伝播」演算子()を提供します。上記のサンプルは書き換えられます
return service?.GetValue()?.Property?.Value;