Comment convertir C # nullable int en int

484

Comment convertir un nullable inten un int? Supposons que j'ai 2 types d'int comme ci-dessous:

int? v1;  
int v2; 

Je veux attribuer v1la valeur de v2. v2 = v1;provoquera une erreur. Comment puis-je convertir v1à v2?

KentZhou
la source
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:

v2 = v1.GetValueOrDefault();
KeithS
la source
4
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.
Ranch Camal
168

Comme ça,

if(v1.HasValue)
   v2=v1.Value
Srinivas Reddy Thatiparthy
la source
92

Vous pouvez utiliser la propriété Value pour l'affectation.

v2 = v1.Value;
e36M3
la source
8
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
Michael Mrozek
82

Tout ce dont tu as besoin c'est..

v2= v1.GetValueOrDefault();
l'étoile
la source
49

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:

v2 = v1 ?? -1;
Guffa
la source
Vous ne devez pas utiliser la valeur sans avoir d'abord vérifié s'il existe une valeur. Utilisez le ?? à la place.
Peter
45

Vous ne pouvez pas le faire si v1 est null, mais vous pouvez vérifier avec un opérateur.

v2 = v1 ?? 0;
Arturo Martinez
la source
28

GetValueOrDefault()

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:

v2= v1.GetValueOrDefault();

Aniket Sharma
la source
21

Si la valeur par défaut pour un type donné est un résultat acceptable:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

Si vous souhaitez une valeur par défaut différente lorsque le résultat n'est pas défini:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

Si vous voulez juste que la valeur soit retournée (que la méthode échoue ou non):

v2 = v1.GetValueOrDefault();


.NET 4.7.2.: Renvoie GetValueOrDefault()la valeur du champ sans aucune vérification.

GrzegorzF
la source
15

En ce qui me concerne, la meilleure solution consiste à utiliser la GetValueOrDefault()méthode.

v2 = v1.GetValueOrDefault();
Masoud Darvishian
la source
celui-ci m'a été le plus utile
Liakat
11

La conversion int nullable en int peut être effectuée comme suit:

v2=(int)v1;
Krishna shidnekoppa
la source
9
Si v1 est null, cela provoquera une InvalidOperationException.
MungeWrath
10

c'est possible avec v2 = Convert.ToInt32(v1);

Tour
la source
Cela fonctionnera techniquement, mais d'autres techniques telles que HasValue / Value ou GetValueOrDefault fonctionnent beaucoup plus efficacement.
Brandon Barkley
9

Vous pourriez faire

v2 = v1.HasValue ? v1.Value : v2;
FIre Panda
la source
9

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;
}
JaredPar
la source
9

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 is int 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.

Nicholas Miller
la source
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.

v2=v1??0

Ou ci-dessous est l'autre façon de l'écrire.

v2 = v1.HasValue?v1:0
Sagar
la source
1

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:

v2 = v1 ?? default;
akesfeden
la source
-1
 int v2= Int32.Parse(v1.ToString());
mohammad qavizi
la source
5
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.
xiawi
1
Il est préférable d'utiliser la méthode des "meilleures pratiques" pour déballer les options au lieu d'utiliser des astuces sournoises. Voir docs.microsoft.com/en-us/dotnet/csharp/language-reference/… pour référence
lorg
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.
Jason Aller