web-dev-qa-db-fra.com

Que signifient deux points d'interrogation ensemble en C #?

A traversé cette ligne de code:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Que signifient les deux points d’interrogation, s’agit-il d’une sorte d’opérateur ternaire? Il est difficile de chercher dans Google.

1412
Edward Tanguay

C'est l'opérateur de coalescence nul et tout à fait comme l'opérateur ternaire (immédiat-si). Voir également ?? Opérateur - MSDN .

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

s'étend à:

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

qui s'étend ensuite à:

if(formsAuth != null)
    FormsAuth = formsAuth;
else
    FormsAuth = new FormsAuthenticationWrapper();

En anglais, cela signifie "Si tout ce qui est à gauche n'est pas nul, utilisez-le, sinon utilisez ce qui est à droite."

Notez que vous pouvez utiliser n'importe quel nombre de ceux-ci en séquence. L'instruction suivante assignera le premier Answer# non nul à Answer (si toutes les réponses sont nulles, la Answer est nulle):

string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;

En outre, même si l’expansion ci-dessus est conceptuellement équivalente, le résultat de chaque expression n’est évalué qu’une fois. Ceci est important si, par exemple, une expression est un appel de méthode avec des effets secondaires. (Nous remercions @ Joey pour l'avoir signalé.)

1900
lc.

Tout simplement parce que personne n’a encore prononcé les mots magiques: c’est l’opérateur de fusion null. Il est défini dans la section 7.12 de la spécification du langage C # 3.0 .

C'est très pratique, notamment à cause de la façon dont cela fonctionne lorsqu'il est utilisé plusieurs fois dans une expression. Une expression de la forme:

a ?? b ?? c ?? d

donnera le résultat de l'expression a s'il est non nul, sinon essayez b, sinon essayez c, sinon essayez d. Il court-circuite à chaque point.

De même, si le type de d est non nullable, le type de l'expression entière n'est pas non plus nullable.

254
Jon Skeet

C'est l'opérateur de coalescence nul.

http://msdn.Microsoft.com/en-us/library/ms173224.aspx

Oui, presque impossible à rechercher à moins de savoir comment ça s'appelle! :-)

EDIT: Et c'est une fonctionnalité intéressante d'une autre question. Vous pouvez les enchaîner.

Fonctionnalités cachées de C #?

67
Iain Holder

Merci à tous, voici l'explication la plus succincte que j'ai trouvée sur le site MSDN:

// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
24
Edward Tanguay

?? est là pour fournir une valeur pour un type nullable lorsque la valeur est null. Ainsi, si formsAuth est null, il renverra un nouveau FormsAuthenticationWrapper (). 

20
RedFilter

enter image description here

Les deux points d'interrogation (??) indiquent qu'il s'agit d'un opérateur de coalescence.

L'opérateur de coalescence renvoie la première valeur NON NULL d'une chaîne. Vous pouvez voir cette vidéo sur youtube qui montre le tout dans sa globalité.

Mais laissez-moi ajouter plus à ce que dit la vidéo.

Si vous voyez que le sens anglais de coalescer signifie anglais, il est écrit «consolidate together». Par exemple, ci-dessous est un simple code coalescent qui chaîne quatre chaînes.

Donc, si str1 est null, il tentera str2, si str2 est null, il tentera str3 et ainsi de suite jusqu'à ce qu'il trouve une chaîne avec une valeur non nulle.

string final = str1 ?? str2 ?? str3 ?? str4;

En mots simples L'opérateur Coalescing renvoie la première valeur NON NULL d'une chaîne. 

18
Shivprasad Koirala

Si vous connaissez Ruby, son ||= me semble ressembler au ?? de C #. Voici quelques rubis:

irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"

Et en C #:

string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
12
Sarah Vessels

Rien de dangereux à ce sujet. En fait, c'est magnifique. Vous pouvez ajouter une valeur par défaut si cela est souhaitable, par exemple:

CODE

int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
11
dqninh

C'est la main courte pour l'opérateur ternaire. 

FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();

Ou pour ceux qui ne font pas ternaire:

if (formsAuth != null)
{
  FormsAuth = formsAuth;
}
else
{
  FormsAuth = new FormsAuthenticationWrapper();
}
11
Benjamin Autin

opérateur de coalescence

c'est équivalent à

FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
10
aku

Pour votre amusement uniquement (sachant que vous êtes tous des gars C # ;-).

Je pense que cela provient de Smalltalk, où il existe depuis de nombreuses années. Il est défini ici comme:

en objet:

? anArgument
    ^ self

dans UndefinedObject (classe de nil):

? anArgument
    ^ anArgument

Il existe des versions évaluant (?) Et non évaluant (??) de this.
On le trouve souvent dans les méthodes getter pour les variables privées (d'instance) initialisées paresseux, qui sont laissées nuls jusqu'à ce qu'elles soient réellement nécessaires.

10
blabla999

Certains exemples d’obtention de valeurs utilisant la fusion sont inefficaces.

Ce que vous voulez vraiment, c'est:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

ou

return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());

Cela empêche l'objet d'être recréé à chaque fois. Au lieu que la variable privée reste null et qu'un nouvel objet soit créé à chaque demande, cela garantit que la variable privée est affectée si le nouvel objet est créé.

9
KingOfHypocrites

Comme indiqué à juste titre dans de nombreuses réponses, il s'agit de "l'opérateur de fusion nul" (??), dont vous pouvez également consulter le cousin, l '"opérateur Null-conditionnel" (? _ ou ? [) qui est un opérateur qui est souvent utilisé conjointement avec ??

Opérateur null-conditionnel

Utilisé pour tester la valeur null avant d'effectuer une opération d'accès membre (?.) Ou d'index (? [). Ces opérateurs vous aident à écrire moins de code pour gérer les contrôles NULL, en particulier pour la descente dans les structures de données.

Par exemple: 

// if 'customers' or 'Order' property or 'Price' property  is null,
// dollarAmount will be 0 
// otherwise dollarAmount will be equal to 'customers.Order.Price'

int dollarAmount = customers?.Order?.Price ?? 0; 

l'ancienne manière sans ?. et ?? de le faire est

int dollarAmount = customers != null 
                   && customers.Order!=null
                   && customers.Order.Price!=null 
                    ? customers.Order.Price : 0; 

ce qui est plus verbeux et encombrant.

9
brakeroo

Remarque:

J'ai lu tout ce fil et bien d'autres, mais je ne trouve pas de réponse aussi complète que celle-ci.

Par ce que j'ai complètement compris le "pourquoi utiliser ?? et quand utiliser ?? et comment utiliser ??."

La source:

La fondation de communication Windows libérée par Craig McMurtry ISBN 0-672-32948-4

Types de valeur nullables

Il existe deux circonstances courantes dans lesquelles on souhaiterait savoir si Une valeur a été affectée à une instance d'un type de valeur. Le premier est lorsque l'instance représente une valeur dans une base de données. Dans un tel cas, on voudrait pouvoir examiner l'instance pour vérifier si une valeur est effectivement présente dans la base de données. L'autre circonstance, qui est plus pertinente pour le sujet de ce livre, est lorsque l'instance représente un élément de données reçu d'une source distante. Là encore, on souhaiterait déterminer à partir de l'instance si une valeur pour cet élément de données a été reçue.

Le .NET Framework 2.0 incorpore une définition de type générique qui fournit des cas comme ceux-ci dans lesquels on veut affecter null à une instance d'un type valeur et tester si la valeur de l'instance est null. Cette définition de type générique est System.Nullable, qui contraint les arguments de type génériques pouvant être substitués à T en types de valeur . Une valeur de null peut être affectée aux instances de types construites à partir de System.Nullable. en effet, leurs valeurs sont nulles par défaut. Ainsi, les types construits à partir de System.Nullable peuvent être appelés types à valeur nullable System.Nullable a une propriété, Value, par laquelle la valeur affectée à une instance de Un type construit à partir de celle-ci peut être obtenu si la valeur de l'instance n'est pas null . On peut donc écrire:

System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}

Le langage de programmation C # fournit une syntaxe abrégée pour la déclaration des types Construite à partir de System.Nullable. Cette syntaxe permet d'abréger:

System.Nullable<int> myNullableInteger;

à

int? myNullableInteger;

Le compilateur empêchera quelqu'un d'essayer d'affecter la valeur d'un type de valeur nullable à un type de valeur ordinaire de la manière suivante:

int? myNullableInteger = null;
int myInteger = myNullableInteger;

Cela empêche personne de le faire car le type de valeur nullable pourrait avoir la valeur null, ce qu'il aurait en réalité dans ce cas, et cette valeur ne peut pas être affectée à un type de valeur ordinaire. Bien que le compilateur permette ce code,

int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;

La deuxième instruction provoquerait une exception, car toute tentative d'accéder à la propriété System.Nullable.Value est une opération non valide si le type .__ construit à partir de System.Nullable n'a pas reçu de valeur valide T, ce qui n'est pas arrivé dans ce cas.

Conclusion:

Une méthode appropriée pour affecter la valeur d'un type de valeur nullable à un type de valeur ordinaire consiste à utiliser la propriété System.Nullable.HasValue pour vérifier si une valeur valide de T a été affectée au type de valeur nullable:

int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}

Une autre option consiste à utiliser cette syntaxe:

int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;

Par lequel l'entier ordinaire myInteger se voit attribuer la valeur de l'entier nullable "myNullableInteger" si ce dernier s'est vu attribuer une valeur entière valide; sinon, la valeur -1 est attribuée à myInteger.

7
Wiqi

L'opérateur ?? s'appelle l'opérateur null-coalescing. Il renvoie l'opérande de gauche si l'opérande n'est pas nul; sinon, il retourne l'opérande de droite.

int? variable1 = null;
int variable2  = variable1 ?? 100;

Définissez variable2 sur la valeur variable1, si variable1 est NON, null, sinon, si variable1 == null, définissez variable2 sur 100.

0
Md.Jubayer

C'est un opérateur de coalescence nul qui fonctionne de la même manière qu'un opérateur ternaire.

    a ?? b  => a !=null ? a : b 

"Un type nullable peut contenir une valeur ou il peut être indéfini" . Donc, si vous essayez d'affecter un type valeur nullable à un type valeur non nullable vous obtiendrez une erreur de compilation.

int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.

Alors faire ça en utilisant ?? opérateur:

z = x ?? 1; // with ?? operator there are no issues
0
Ashish Mishra
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

est équivalent à 

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

Mais l’avantage, c’est que vous pouvez les enchaîner, comme d’autres personnes l’ont dit ... La seule chose qui n’a pas été abordée, c’est que vous pouvez l’utiliser pour lancer une exception.

A = A ?? B ?? throw new Exception("A and B are both NULL");
0
NolePTR