Quelle est la différence entre les options et le type Nullable

15

Swift l'a fait Optionals. C # a des Nullabletypes.

Pour autant que je sache, les deux ont le même objectif, outre la valeur d'un certain type, ils stockent des informations sur la variable ou non (non initialisée).

La question est Optionalsjuste des Nullabletypes avec un nom différent ou y a-t-il d'autres différences conceptuelles?

En d'autres termes, parler du concept lui-même, ou dans le contexte de langues qui n'ont pas Optionalsou Nullables, quel est le terme utilisé?

Lors de la mise en œuvre de cette fonctionnalité dans la langue, importe-t-il que je nomme le type Optionals<T>ouNullable<T>

Dalija Prasnikar
la source
D'un point de vue indépendant de la langue, ils sont identiques. Cela dit, un langage peut différencier les concepts (par exemple, si la correspondance des modèles est appliquée ou non).
Thomas Eding
C # peut aussi avoir des options (c'est juste un modèle monadique): github.com/louthy/language-ext
Den
2
L'utilisation d'une référence nulle (ou d'un pointeur NULL, dans les langues avec pointeurs) est un hack que certaines langues utilisent pour représenter des valeurs facultatives, c'est-à-dire un conteneur qui peut avoir une valeur ou aucune valeur. Cela a la limitation que vous ne pouvez considérer comme facultatif qu'un type basé sur des références (ou des pointeurs). Ainsi, par exemple, en Java, vous ne pouvez pas rendre un entier facultatif sans l'envelopper dans un objet (par exemple Integer). D'autres langages proposent des types facultatifs comme types génériques qui peuvent envelopper n'importe quel autre type, par exemple Peut-être dans Haskell, Option dans Scala, etc.
Giorgio

Réponses:

5

Il y a une connotation différente, même si elles fonctionnent de manière très similaire. Tout le monde sauf Microsoft (insérez le œil ici) utilise nullet nullableuniquement dans le contexte des références. Optionset Maybessont généralement compris comme faisant référence à la fois aux références et aux valeurs, en particulier dans les langages de programmation fonctionnels où la transparence référentielle signifie qu'il n'y a pas beaucoup de différence entre une valeur et une référence.

En d'autres termes, parler du concept lui-même, ou dans le contexte de langages qui n'ont pas Optionalsou Nullables, quel est le terme utilisé?

Optionsest le terme qui provoque le moins de confusion parmi un large public. Seuls les programmeurs C # considéreront un Nullablecomme potentiellement applicable à un type de valeur, et je pense que la plupart d'entre eux sont au moins conscients de ce qu'est un Option.

Karl Bielefeldt
la source
Tout le monde sauf Microsoft et les concepteurs de SQL, je pense que vous voulez dire.
Jules
9

Dans .NET, il existe deux catégories de types: les références et les valeurs (int, double, structs, enums, etc.). Parmi leurs différences, il y a le fait qu'une référence peut être null, alors qu'une valeur ne peut pas. Ainsi, si vous avez un type de valeur et que vous souhaitez transmettre une sémantique "facultative" ou "inconnue", vous pouvez l'orner avec Nullable<>. Notez qu'il Nullable<>est contraint par type à n'accepter que les types de valeur (il a une where T : structclause). Nullable<>a également des avantages spéciaux du compilateur grâce auxquels une nullvaleur est protégée contre NullReferenceExceptions:

string x = null;
x.ToString(); // throws a NullReferenceException

int? y = null;
y.ToString(); // returns ""

Dans les langages fonctionnels (comme Scala, F #, Haskell, Swift, etc.), il est courant nullde ne pas exister . En effet, dans l'ensemble, les gens considèrent l'existence de nullcomme une mauvaise idée , et les concepteurs de langage ont décidé de résoudre ce problème en le refusant.

Cela signifie que nous avons encore besoin d'un moyen de représenter une non-valeur dans ces langues. Entrez le Optiontype (la nomenclature varie, cela s'appelle Maybeen Haskell). Cela fait un travail similaire à Nullableen ce qu'il encapsule un type pour ajouter le cas où la valeur est "Aucun" ou "Inconnu" etc.

La vraie différence réside dans les fonctions supplémentaires qui vous sont offertes par les langages qui implémentent Option. À titre d'exemple, prenez Option.map(en pseudocode):

function Option<T2> Option.map(opt: Option<T1>, mapFunc: T1 -> T2) {
    if (opt is None) return None
    else return Option<T2>(mapFunc(opt.Value))
}

Le chaînage de fonctions comme Option.mapest un moyen puissant d'éviter le passe-partout de vérification nulle typique que vous voyez partout en C #:

if (service == null)
    return null;
var x = service.GetValue();
if (x == null || x.Property == null)
    return null;
return x.Property.Value;

L'équivalent nul en C # serait:

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);
}

Cependant, cela a une utilité limitée en C # car cela ne fonctionnera que pour les types de valeur.

La nouvelle version de C # propose l'opérateur "propagation nulle" ( ?.) qui est similaire à la Option.mapfonction sauf qu'il n'est applicable qu'aux méthodes et aux accesseurs de propriété. L'échantillon ci-dessus serait réécrit

return service?.GetValue()?.Property?.Value;
AlexFoxGill
la source
C # est un langage fonctionnel impur (tout comme F #). F # a également des valeurs nulles.
Den
C # 6 a une valeur nulle, donc au moins une partie de votre code n'est pas à jour: github.com/dotnet/roslyn/wiki/… roslyn.codeplex.com/discussions/540883
Den
De plus, les options sont faciles à mettre en œuvre: github.com/louthy/language-ext
Den
1
@Den: C # penche vers OOP tandis que F # penche vers FP. L'absence de curry et de mutabilité par défaut signifie que C # n'est pas approprié pour une programmation fonctionnelle sérieuse. J'ai mentionné la propagation nulle à la fin de la réponse. Les options sont en effet simples à implémenter en C # mais cela s'écarte de la question.
AlexFoxGill
4
@ Den, je pense qu'il y a un mauvais choix de mots dans vos commentaires. Un langage fonctionnel impur est un langage fonctionnel qui permet des effets secondaires. C # peut avoir certaines fonctionnalités et vous pouvez les utiliser à bon escient, mais ce n'est pas un langage fonctionnel. Je suppose que vous vouliez dire qu'aucun des deux langages n'est 100% fonctionnel, mais F # est très proche d'OCaml qui est par la plupart des comptes un langage fonctionnel. Quels que soient les écarts qu'il fait par rapport au paradigme fonctionnel, ils peuvent principalement interagir avec du code .NET étranger. Par exemple, ce nulln'est pas une valeur valide pour les types F #.
Doval