Parcourez 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 rechercher dans Google.
Parcourez 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 rechercher dans Google.
Réponses:
C'est l'opérateur coalescent nul, et tout comme l'opérateur ternaire (immédiat-si). Voir aussi ?? Opérateur - MSDN .
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
s'étend à:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
qui s'élargit encore à:
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 dans l'ordre. L'instruction suivante affectera le premier non nul Answer#
à Answer
(si toutes les réponses sont nulles, le Answer
est nul):
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
Il convient également de mentionner que, si l'expansion ci-dessus est conceptuellement équivalente, le résultat de chaque expression n'est évalué qu'une seule fois. Ceci est important si, par exemple, une expression est un appel de méthode avec des effets secondaires. (Nous remercions @Joey de l'avoir signalé.)
??
est laissé associatif, a ?? b ?? c ?? d
est donc équivalent à ((a ?? b) ?? c ) ?? d
. "Les opérateurs d'affectation et l'opérateur ternaire (? :) sont associatifs à droite. Tous les autres opérateurs binaires sont associatifs à gauche." Source: msdn.microsoft.com/en-us/library/ms173145.aspx
Tout simplement parce que personne d'autre n'a encore prononcé les mots magiques: c'est l' opérateur de coalescence nul . Il est défini dans la section 7.12 de la spécification du langage C # 3.0 .
C'est très pratique, en particulier en raison de la façon dont il 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
si elle n'est pas nulle, sinon essayez b
, sinon essayez c
, sinon essayez d
. Il court-circuite en tout point.
De plus, si le type de d
est non nullable, le type de l'expression entière est non nullable également.
C'est l'opérateur coalescent nul.
http://msdn.microsoft.com/en-us/library/ms173224.aspx
Oui, presque impossible à rechercher à moins de savoir comment on l'appelle! :-)
EDIT: Et ceci est une fonctionnalité intéressante d'une autre question. Vous pouvez les enchaîner.
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;
-1
est juste un simple int
, qui n'est pas nullable).
x
est de type int?
mais y
de type int
, vous pouvez écrire int y = (int)(x ?? -1)
. Il analysera x
à un int
si ce n'est pas null
, ou céder -1
à y
si x
est null
.
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 youtube qui montre le tout pratiquement.
Mais permettez-moi d'ajouter plus à ce que dit la vidéo.
Si vous voyez le sens anglais de coalescence, il dit «consolider ensemble». Par exemple ci-dessous est un simple code coalescent qui enchaîne quatre chaînes.
Donc, s'il l' str1
est, null
il essaiera str2
, s'il l' str2
est, null
il essayera 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 termes simples, l'opérateur de coalescence renvoie la première valeur NON NULL d'une chaîne.
C'est une main courte pour l'opérateur ternaire.
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
Ou pour ceux qui ne font pas de ternaire:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
!= null
) et le second formsAuth
(après le ?
) peuvent être modifiés; sous la forme null coalesce, les deux prennent implicitement les valeurs que vous avez fournies.
Si vous êtes familier avec Ruby, cela me ||=
ressemble aux 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";
x ||= y
desugars à quelque chose comme x = x || y
, donc ??
est en fait plus similaire à plain ||
en Ruby.
??
seuls soucis au sujet null
, alors que l' ||
opérateur Ruby, comme dans la plupart des langues, est plus sur null
, false
ou tout ce qui peut être considéré comme une valeur booléenne avec une valeur de false
(par exemple , dans certaines langues, ""
). Ce n'est pas une bonne ou une mauvaise chose, simplement une différence.
Rien de dangereux à ce sujet. En fait, c'est beau. Vous pouvez ajouter une valeur par défaut si cela est souhaitable, par exemple:
CODE
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
int? x1 = null;
est-ce vrai
x1
- x4
DOIT être de type nullable: cela n'a aucun sens de dire, effectivement, "le résultat est 0
if x4
est une valeur qu'il ne peut pas prendre" ( null
). Le "type nullable" inclut ici les types de valeur nullable et les types de référence, bien sûr. Il s'agit d'une erreur au moment de la compilation si une ou plusieurs des variables chaînées (à l'exception de la dernière) ne peuvent pas être annulées.
Comme indiqué à juste titre dans de nombreuses réponses, il s'agit de l '"opérateur de coalescence nul" ( ?? ), à propos duquel vous voudrez peut-être également consulter son cousin "l'opérateur Null-conditionnel" ( ?. Ou ? [ ) Qui est un opérateur qui plusieurs fois, il est utilisé en conjonction avec ??
Utilisé pour tester la valeur null avant d'effectuer une opération d'accès aux membres ( ?. ) Ou d'index ( ? [ ). Ces opérateurs vous aident à écrire moins de code pour gérer les vérifications nulles, en particulier pour descendre 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 sans ?. et ?? de le faire est
int dollarAmount = customers != null
&& customers.Order!=null
&& customers.Order.Price!=null
? customers.Order.Price : 0;
qui est plus verbeux et encombrant.
Pour votre amusement uniquement (sachant que vous êtes tous des gars C # ;-).
Je pense qu'il est originaire de Smalltalk, où il existe depuis de nombreuses années. Il y est défini comme:
dans Object:
? anArgument
^ self
dans UndefinedObject (aka la classe de nil):
? anArgument
^ anArgument
Il existe à la fois des versions d'évaluation (?) Et non d'évaluation (??).
On le trouve souvent dans les méthodes getter pour les variables privées (instance) initialisées paresseux, qui restent nuls jusqu'à ce qu'elles soient vraiment nécessaires.
Certains des exemples d'obtention de valeurs à l'aide de la coalescence 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 nulle 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éé.
??
raccourci n'est-il pas évalué? new FormsAuthenticationWrapper();
est évalué si et seulement si _formsAuthWrapper
est nul.
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 lequel j'ai complètement compris le "pourquoi utiliser ?? et quand utiliser ?? et comment utiliser ??."
Lancement de la fondation de communication Windows Par Craig McMurtry ISBN 0-672-32948-4
Il existe deux circonstances courantes dans lesquelles on souhaite 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 aimerait pouvoir examiner l'instance pour vérifier si une valeur est bien 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. Encore une fois, on voudrait 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 prévoit des cas comme ceux-ci dans lesquels on veut attribuer null à une instance d'un type de valeur et tester si la valeur de l'instance est nulle. Cette définition de type générique est System.Nullable, qui contraint les arguments de type générique qui peuvent être substitués pour T aux types de valeur. Les instances de types construites à partir de System.Nullable peuvent se voir attribuer une valeur nulle; en effet, leurs valeurs sont nulles par défaut. Ainsi, les types construits à partir de System.Nullable peuvent être appelés types de valeurs nullables. System.Nullable a une propriété, Value, par laquelle la valeur affectée à une instance d'un type construit à partir de celle-ci peut être obtenue si la valeur de l'instance n'est pas nulle. Par conséquent, on peut é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 déclarer des types construits à partir de System.Nullable. Cette syntaxe permet d'abréger:
System.Nullable<int> myNullableInteger;
à
int? myNullableInteger;
Le compilateur empêchera de tenter d'affecter la valeur d'un type de valeur nullable à un type de valeur ordinaire de cette façon:
int? myNullableInteger = null;
int myInteger = myNullableInteger;
Cela l'empêche de le faire car le type de valeur nullable pourrait avoir la valeur null, ce qu'il aurait en fait dans ce cas, et cette valeur ne peut pas être affectée à un type de valeur ordinaire. Bien que le compilateur autorise ce code,
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
La deuxième instruction entraînerait la levée d'une exception car toute tentative d'accès à 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 de T, ce qui ne s'est pas produit dans ce Cas.
Une façon appropriée d'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 a reçu une valeur entière valide; sinon, myInteger reçoit la valeur -1.
C'est un opérateur coalescent nul qui fonctionne de manière similaire à un opérateur ternaire.
a ?? b => a !=null ? a : b
Un autre point intéressant pour cela est, "Un type nullable peut contenir une valeur, ou il peut être indéfini" . Donc, si vous essayez d'affecter un type de valeur nullable à un type de 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.
Donc, pour ce faire en utilisant ?? opérateur:
z = x ?? 1; // with ?? operator there are no issues
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
est équivalent à
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
Mais ce qu'il y a de bien, c'est que vous pouvez les enchaîner, comme d'autres l'ont dit. La seule chose qui n'est pas abordée est que vous pouvez réellement l'utiliser pour lever une exception.
A = A ?? B ?? throw new Exception("A and B are both NULL");
L' ??
opérateur est appelé l'opérateur de coalescence nulle. Il renvoie l'opérande de gauche si l'opérande n'est pas nul; sinon, elle renvoie l'opérande de droite.
int? variable1 = null;
int variable2 = variable1 ?? 100;
Définissez variable2
la valeur de variable1
, si variable1
n'est PAS nul; sinon, si variable1 == null
, réglé variable2
sur 100.
D'autres l'ont décrit Null Coalescing Operator
assez bien. Pour ceux qui sont intéressés, il existe une syntaxe raccourcie où cela (la question SO):
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
est équivalent à ceci:
FormsAuth ??= new FormsAuthenticationWrapper();
Certains le trouvent plus lisible et succinct.