Quel est le comportement souhaité quand v1est null?
Solomon Ucko
Réponses:
637
Jusqu'à présent, les autres réponses sont toutes correctes; Je voulais juste en ajouter un de plus légèrement plus propre:
v2 = v1 ??default(int);
Any Nullable<T>est implicitement convertible en son T, à condition que l'expression entière en cours d'évaluation ne puisse jamais entraîner une affectation nulle à un ValueType. Ainsi, l'opérateur de coalescence nulle ??n'est qu'un sucre de syntaxe pour l'opérateur ternaire:
v2 = v1 ==null?default(int): v1;
... qui est à son tour du sucre de syntaxe pour un if / else:
if(v1==null)
v2 =default(int);else
v2 = v1;
En outre, à partir de .NET 4.0, Nullable<T>a une méthode "GetValueOrDefault ()", qui est un getter sans danger qui effectue essentiellement la fusion nulle illustrée ci-dessus, donc cela fonctionne aussi:
Est-ce default(int)vraiment nécessaire? Quel est le problème avec un simple 0?
Cole Johnson
4
Cela fonctionnerait pour cet exemple, mais dans le cas général, il est recommandé d'utiliser le defaultcas échéant. Zéro n'est pas toujours valide en tant que valeur, encore moins la valeur par défaut, donc si vous remplacez intpar un générique, Tvous trouverez que mon code fonctionne tandis que zéro ne fonctionne pas. Dans une future version du framework, defaultpeut également devenir surchargeable; si et quand cela se produit, le code utilisant la valeur par défaut pourra facilement en profiter, tandis que les affectations explicites nulles ou nulles devront être modifiées.
KeithS
5
Cela devrait monter en haut: .NET 4.0, Nullable <T> a un "GetValueOrDefault ()"
RandomHandle
Merci d'être revenu pour le modifier avec GetValueOrDefault!
CindyH
Vous pouvez être prudent avec DateTime lorsque vous utilisez par défaut. Cela pourrait insérer la date par défaut au lieu de vide.
De plus, si vous n'êtes pas sûr que v1 contienne null, vous pouvez utiliser l'opérateur de coalescence nulle pour définir une valeur de secours. Par exemple v2 = v1 ?? 0;
Arjen
12
Et assurez-vous de vérifier d' v1.HasValueabord.
Beurk
3
MSDN dit que cela va lancer une exception si l' v1est null. À mon avis, ce n'est pas une bonne réponse.
ventiseis
6
@ventiseis Je pense que c'est un comportement souhaitable - je suis surpris que de nombreuses autres réponses acceptent de convertir silencieusement un null en 0. Si vous attribuez un type nullable à un type non nullable, vous devez être sûr que la valeur n'est pas réellement nulle. OP n'a pas dit "je veux assigner v1 à v2, ou 0 si v1 est nul", mais c'est ce que tout le monde semblait supposer
Si vous savez que cela v1a une valeur, vous pouvez utiliser la Valuepropriété:
v2 = v1.Value;
L'utilisation de la GetValueOrDefaultméthode affectera la valeur s'il y en a une, sinon la valeur par défaut pour le type ou une valeur par défaut que vous spécifiez:
v2 = v1.GetValueOrDefault();// assigns zero if v1 has no value
v2 = v1.GetValueOrDefault(-1);// assigns -1 if v1 has no value
Vous pouvez utiliser la HasValuepropriété pour vérifier si v1a une valeur:
if(v1.HasValue){
v2 = v1.Value;}
Il existe également un support linguistique pour la GetValueOrDefault(T)méthode:
Une conversion simple entre v1et v2n'est pas possible car v1a un domaine de valeurs plus grand que v2. C'est tout ce qui v1peut contenir plus l' nullÉtat. Pour convertir, vous devez indiquer explicitement quelle valeur intsera utilisée pour mapper l' nullétat. La façon la plus simple de le faire est l' ??opérateur
v2 = v1 ??0;// maps null of v1 to 0
Cela peut également être fait sous forme longue
int v2;if(v1.HasValue){
v2 = v1.Value;}else{
v2 =0;}
En fonction de votre contexte d'utilisation, vous pouvez utiliser la fonction de correspondance de modèles de C # 7:
int? v1 =100;if(v1 isint v2){Console.WriteLine($"I'm not nullable anymore: {v2}");}
ÉDITER:
Étant donné que certaines personnes votent vers le bas sans laisser d'explication, je voudrais ajouter quelques détails pour expliquer la raison pour laquelle cela est considéré comme une solution viable.
La correspondance de motifs de C # 7 nous permet désormais de vérifier le type d'une valeur et de la transposer implicitement. Dans l'extrait ci-dessus, la condition if ne passe que lorsque la valeur stockée dans v1est compatible avec le type for v2, ce qui est le cas dans ce cas int. Il s'ensuit que lorsque la valeur de v1est null, la condition if échouera car nul ne peut être affecté à un int. Plus correctement, nulln'est pas un int.
Je voudrais souligner que cette solution n'est peut-être pas toujours le choix optimal. Comme je le suggère, je pense que cela dépendra du contexte d'utilisation exact du développeur. Si vous avez déjà un int?et que vous souhaitez opérer sous condition sur sa valeur si et seulement si la valeur affectée n'est pas nulle (c'est la seule fois où il est sûr de convertir un entier nullable en un entier normal sans perdre d'informations), alors la correspondance de motifs est peut-être l'un des moyens les plus concis de le faire.
La nécessité d'introduire un nouveau nom de variable est regrettable, mais c'est la meilleure solution (la plus sûre) s'il n'y a pas de valeur par défaut, car il n'y a aucun risque de refactoriser accidentellement vos HasValuechèques.
minexew
Je ne vois tout simplement aucun avantage à cette méthode par rapport à v1.HasValue comme vérification, puis v1.Value pour accéder à la valeur sous-jacente. Je ne voterais pas pour cela, mais je pense que ce problème a déjà été résolu et une nouvelle technique n'ajoute pas beaucoup de clarté au problème. Je l'ai également comparé à 8-9% plus lent.
Brandon Barkley
Merci de l'avoir comparé, c'est bon à savoir! Quoi qu'il en soit, la différence est au mieux marginale (à moins que vous ne le fassiez dans un domaine critique, je suppose). Je considère que cela est plus "concis" ou peut-être "idiomatique" car il repose sur des sucres de syntaxe cuits dans le langage plutôt que sur des API. C'est un peu subjectif, mais c'est peut-être "plus facile à maintenir". Bien que vraiment, j'aime cette approche plus que de compter sur une valeur par défaut comme le suggèrent de nombreuses autres réponses.
Nicholas Miller
3
Il affectera la valeur de v1à v2s'il n'est pas nul, sinon il prendra une valeur par défaut comme zéro.
Dans C # 7.1 et versions ultérieures, le type peut être déduit en utilisant le defaultlittéral au lieu de l' defaultopérateur afin qu'il puisse être écrit comme ci-dessous:
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant pourquoi et / ou comment ce code répond à la question améliore sa valeur à long terme.
Lorsque vous répondez à une question de huit ans avec quinze réponses existantes, il est important d'expliquer à quel nouvel aspect de la question votre réponse répond et de noter si le temps a changé la réponse. Les réponses codées uniquement peuvent presque toujours être améliorées par l'ajout d'explications.
v1
estnull
?Réponses:
Jusqu'à présent, les autres réponses sont toutes correctes; Je voulais juste en ajouter un de plus légèrement plus propre:
Any
Nullable<T>
est implicitement convertible en sonT
, à condition que l'expression entière en cours d'évaluation ne puisse jamais entraîner une affectation nulle à un ValueType. Ainsi, l'opérateur de coalescence nulle??
n'est qu'un sucre de syntaxe pour l'opérateur ternaire:... qui est à son tour du sucre de syntaxe pour un if / else:
En outre, à partir de .NET 4.0,
Nullable<T>
a une méthode "GetValueOrDefault ()", qui est un getter sans danger qui effectue essentiellement la fusion nulle illustrée ci-dessus, donc cela fonctionne aussi:la source
default(int)
vraiment nécessaire? Quel est le problème avec un simple0
?default
cas échéant. Zéro n'est pas toujours valide en tant que valeur, encore moins la valeur par défaut, donc si vous remplacezint
par un générique,T
vous trouverez que mon code fonctionne tandis que zéro ne fonctionne pas. Dans une future version du framework,default
peut également devenir surchargeable; si et quand cela se produit, le code utilisant la valeur par défaut pourra facilement en profiter, tandis que les affectations explicites nulles ou nulles devront être modifiées.Comme ça,
la source
Vous pouvez utiliser la propriété Value pour l'affectation.
la source
v1.HasValue
abord.v1
estnull
. À mon avis, ce n'est pas une bonne réponse.Tout ce dont tu as besoin c'est..
la source
Si vous savez que cela
v1
a une valeur, vous pouvez utiliser laValue
propriété:L'utilisation de la
GetValueOrDefault
méthode affectera la valeur s'il y en a une, sinon la valeur par défaut pour le type ou une valeur par défaut que vous spécifiez:Vous pouvez utiliser la
HasValue
propriété pour vérifier siv1
a une valeur:Il existe également un support linguistique pour la
GetValueOrDefault(T)
méthode:la source
Vous ne pouvez pas le faire si v1 est null, mais vous pouvez vérifier avec un opérateur.
la source
récupère la valeur de l'objet. S'il est nul, il renvoie la valeur par défaut de int, qui est 0.
Exemple:
la source
Si la valeur par défaut pour un type donné est un résultat acceptable:
Si vous souhaitez une valeur par défaut différente lorsque le résultat n'est pas défini:
Si vous voulez juste que la valeur soit retournée (que la méthode échoue ou non):
.NET 4.7.2.: Renvoie
GetValueOrDefault()
la valeur du champ sans aucune vérification.la source
En ce qui me concerne, la meilleure solution consiste à utiliser la
GetValueOrDefault()
méthode.la source
La conversion int nullable en int peut être effectuée comme suit:
la source
c'est possible avec
v2 = Convert.ToInt32(v1);
la source
Vous pourriez faire
la source
Une conversion simple entre
v1
etv2
n'est pas possible carv1
a un domaine de valeurs plus grand quev2
. C'est tout ce quiv1
peut contenir plus l'null
État. Pour convertir, vous devez indiquer explicitement quelle valeurint
sera utilisée pour mapper l'null
état. La façon la plus simple de le faire est l'??
opérateurCela peut également être fait sous forme longue
la source
En fonction de votre contexte d'utilisation, vous pouvez utiliser la fonction de correspondance de modèles de C # 7:
ÉDITER:
Étant donné que certaines personnes votent vers le bas sans laisser d'explication, je voudrais ajouter quelques détails pour expliquer la raison pour laquelle cela est considéré comme une solution viable.
La correspondance de motifs de C # 7 nous permet désormais de vérifier le type d'une valeur et de la transposer implicitement. Dans l'extrait ci-dessus, la condition if ne passe que lorsque la valeur stockée dans
v1
est compatible avec le type forv2
, ce qui est le cas dans ce casint
. Il s'ensuit que lorsque la valeur dev1
estnull
, la condition if échouera car nul ne peut être affecté à unint
. Plus correctement,null
n'est pas unint
.Je voudrais souligner que cette solution n'est peut-être pas toujours le choix optimal. Comme je le suggère, je pense que cela dépendra du contexte d'utilisation exact du développeur. Si vous avez déjà un
int?
et que vous souhaitez opérer sous condition sur sa valeur si et seulement si la valeur affectée n'est pas nulle (c'est la seule fois où il est sûr de convertir un entier nullable en un entier normal sans perdre d'informations), alors la correspondance de motifs est peut-être l'un des moyens les plus concis de le faire.la source
HasValue
chèques.Il affectera la valeur de
v1
àv2
s'il n'est pas nul, sinon il prendra une valeur par défaut comme zéro.Ou ci-dessous est l'autre façon de l'écrire.
la source
Dans C # 7.1 et versions ultérieures, le type peut être déduit en utilisant le
default
littéral au lieu de l'default
opérateur afin qu'il puisse être écrit comme ci-dessous:la source
la source