web-dev-qa-db-ja.com

Optional型とNullable型の違いは何ですか

SwiftにはOptionalsがあります。 C#にはNullableタイプがあります。

両方が同じ目的を果たしていると私が知る限り、変数には値があるかどうか、または未定義(初期化されていない)かどうかの情報がいくつかの型の値に保存されます。

問題は、名前が異なるOptionalsNullable型だけですか、それとも他の概念的な違いがありますか?

言い換えれば、コンセプト自体について、またはOptionalsNullablesを持たない言語のコンテキストで話す場合、どの用語が使用されるかは重要ですか?

言語でその機能を実装するとき、type Optionals<T>またはNullable<T>

15

動作は非常に似ていますが、異なる意味合いがあります。 Microsoft以外の全員(ここにアイロールを挿入)は、参照のコンテキストでのみnullおよびnullableを使用します。 OptionsMaybesは、参照と値の両方を指すと一般に理解されています。特に、関数型プログラミング言語では、参照の透過性により値と参照の間に大きな違いはありません。

言い換えると、コンセプト自体について、またはOptionalsNullablesを持たない言語のコンテキストについて話す場合、どの用語が使用されているかは重要ですか?

Optionsは、幅広いオーディエンス間の混乱を最小限に抑えるための用語です。 C#プログラマーだけがNullableを値の型に適用する可能性があると考えますが、それらのほとんどは少なくともOptionが何であるかを認識していると思います。

5
Karl Bielefeldt

.NETには、referencesvaluesの2つのタイプのカテゴリがあります。 (int、double、struct、enumなど)。それらの違いの中には、参照が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タイプを入力します(命名法は異なり、HaskellではMaybeと呼ばれます)。これは、値が「なし」または「不明」などのケースを追加するために型をラップするという点で、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#の新しいバージョンでは、「null伝播」演算子(?.)が提供されています。これは、メソッドとプロパティアクセサーにのみ適用できることを除いて、Option.map関数と似ています。上記のサンプルは書き換えられます

return service?.GetValue()?.Property?.Value;
9
AlexFoxGill