В чем разница между необязательными и Nullable типом


15

Свифт имеет Optionals. C # имеет Nullableтипы.

Насколько я могу судить, оба служат одной и той же цели, кроме значения некоторого типа, они хранят информацию о том, имеет ли переменная значение или не определена (неинициализирована).

Вопрос в том, Optionalsчто это просто Nullableтипы с другим именем или есть другие концептуальные различия?

Другими словами, говорить о самом понятии, или в контексте языков, которые не имеют Optionalsили Nullablesимеет значение, какой термин используется?

При реализации этой функциональности на языке имеет значение, назову ли я тип Optionals<T>илиNullable<T>


С языковой независимости они идентичны. Тем не менее, язык может дифференцировать понятия (например, применяется ли сопоставление с образцом).
Томас Эдинг

C # может иметь варианты тоже (это просто монадическая рисунок): github.com/louthy/language-ext
Den

2
Использование нулевой ссылки (или указателя NULL в языках с указателями) - это хак, который некоторые языки используют для представления необязательных значений, то есть контейнера, который может иметь одно значение или не иметь значения вообще. Это имеет ограничение, что вы можете считать необязательным тип, основанный на ссылках (или указателях). Так, например, в Java вы не можете сделать целое число необязательным, не заключая его в объект (например, Integer). Другие языки предоставляют необязательные типы в качестве универсальных типов, которые могут переносить любой другой тип, например, Maybe в Haskell, Option в Scala и так далее.
Джорджио

Ответы:


5

Существует разная коннотация, хотя они работают очень схожим образом. Все, кроме Microsoft (вставьте здесь зрелище), используют nullи nullableтолько в контексте ссылок. Optionsи Maybesобычно понимается как относящийся к ссылкам и значениям, особенно в функциональных языках программирования, где прозрачность по ссылкам означает, что между значением и ссылкой нет большой разницы.

Другими словами, речь идет о самом понятии, или в контексте языков, которые не имеют Optionalsили Nullablesимеет значение, какой термин используется?

Optionsэто термин, который вызывает наименьшее замешательство среди широкой аудитории. Только программисты на C # могут думать о том, Nullableчто они потенциально применимы к типу значения, и я думаю, что большинство из них, по крайней мере, знают, что Optionтакое.


Все, кроме Microsoft и разработчиков SQL, я думаю, вы имеете в виду.
Жюль

9

В .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;

C # является нечистым функциональным языком (так же, как F #). Также у F # есть нули.
День

C # 6 имеет нулевое значение принуждением, так по крайней мере , некоторые из вашего кода не в курсе: github.com/dotnet/roslyn/wiki/... roslyn.codeplex.com/discussions/540883
Den

Также параметры легко реализовать: github.com/louthy/language-ext
Den

1
@Den: C # наклоняется к ООП, в то время как F # наклоняется к FP. Отсутствие каррирования и изменчивости по умолчанию означает, что C # не подходит для серьезного функционального программирования. Я упомянул нулевое распространение в конце ответа. Опции действительно просты в реализации в C #, но это отходит от вопроса.
AlexFoxGill

4
@ Думаю, в твоих комментариях плохой выбор слов. Нечистый функциональный язык - это функциональный язык, который допускает побочные эффекты. C # может иметь некоторые функциональные возможности, и вы можете использовать их с большим эффектом, но это не функциональный язык. Я предполагаю, что вы имели в виду, что ни один из языков не является на 100% функциональным, но F # очень близок к OCaml, который по большинству счетов является функциональным языком. Какие бы отклонения он ни делал от функциональной парадигмы, в основном он существует, поэтому он может взаимодействовать с чужим кодом .NET. Показательный пример, nullне является допустимым значением для типов F #.
Довал
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.