В .NET есть две категории типов: ссылки и значения (int, double, структуры, перечисления и т. Д.). Среди их отличий тот факт, что ссылка может быть 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
на Хаскеле). Это делает работу, аналогичную 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 #:
if (service == null)
return null;
var x = service.GetValue();
if (x == null || x.Property == null)
return null;
return x.Property.Value;
Обнуляемый эквивалент в C # будет:
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
функцию, за исключением того, что он применим только для методов и методов доступа к свойствам. Приведенный выше пример будет переписан
return service?.GetValue()?.Property?.Value;