Яка різниця між необов'язковими та типовими Nullable


15

Свіфт має Optionals. C # має Nullableтипи.

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

Питання - це Optionalsлише Nullableтипи з різною назвою чи є інші концептуальні відмінності?

Іншими словами, якщо говорити про саму концепцію, чи в контексті мов, які не мають, Optionalsчи Nullablesмає значення який термін використовується?

При реалізації цієї функції мовою не має значення, чи я називаю тип Optionals<T>абоNullable<T>


З мовної агностичної точки зору, вони однакові. Однак, мова може диференціювати поняття (наприклад, чи застосовується відповідність шаблону чи ні).
Томас Едінг

C # може мати варіанти теж (це просто Монадический малюнок): github.com/louthy/language-ext
Den

2
Використання нульової посилання (або вказівника NULL, у мовах з покажчиками) є хак, який деякі мови використовують для представлення необов'язкових значень, тобто контейнер, який може мати одне значення або взагалі не мати значення. Це обмеження, що ви можете вважати лише необов'язковим тип, який базується на посиланнях (або покажчиках). Так, наприклад, в Java ви не можете зробити ціле число необов’язковим, не загорнувши його в об'єкт (наприклад, Integer). Інші мови надають необов'язкові типи як загальні типи, які можуть обгортати будь-який інший тип, наприклад, можливо, у Haskell, Option у Scala тощо.
Джорджіо

Відповіді:


5

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

Іншими словами, якщо говорити про саму концепцію, чи в контексті мов, які не мають, Optionalsчи Nullablesмає значення, який термін використовується?

Optionsце термін, який викликає найменше плутанину серед широкої аудиторії. Лише програмісти на C # будуть вважати, що це Nullableпотенційно застосовується до типу значень, і я думаю, що більшість з них принаймні знає, що Optionтаке.


Думаю, що ви, крім Microsoft, і дизайнери SQL.
Жуль

9

У .NET є дві категорії типу: посилання та значення (int, double, structs, enums тощо). Серед їх відмінностей є той факт, що посилання може бути 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що він містить тип, щоб додати випадок, коли значенням є "None" або "Unknown" і т.д.

Справжня різниця полягає в додаткових функціях, що надаються вам мовами, які реалізують 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;

Еквівалент Nullable в 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 # пропонує оператор "null розповсюдження" ( ?.), який аналогічний 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 # нахиляється до OOP, тоді як F # нахиляється до FP. Відсутність currying і незмінність за замовчуванням засоби C # не підходять для серйозних функціональних програмувань. У кінці відповіді я згадав про нульове поширення. Варіанти дійсно просто реалізувати в C #, але це відходить від питання.
AlexFoxGill

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