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




signification point d'interrogation sms (13)

Ran à 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 regarder dans Google.


Remarque:

J'ai lu tout ce fil et beaucoup d'autres mais je ne peux pas trouver une réponse aussi approfondie que cela.

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

La source:

Fondation de communication Windows déchaînée par Craig McMurtry ISBN 0-672-32948-4

Types de valeur nullable

Il y a deux circonstances communes dans lesquelles on aimerait savoir si une valeur a été assignée à une instance d'un type de valeur. La première 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 effectivement présente dans la base de données. L'autre circonstance, qui est plus pertinente pour l'objet de ce livre, est lorsque l'instance représente un élément de données reçu d'une source éloignée. Encore une fois, on aimerait 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 assigner 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 remplacer T par des types de valeur. Les instances de types construits à partir de System.Nullable peuvent recevoir une valeur null. en effet, leurs valeurs sont nulles par défaut. Ainsi, les types construits à partir de System.Nullable peuvent être appelés types de valeur Nullable. 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 les types construits à partir de System.Nullable. Cette syntaxe permet d'abréger:

System.Nullable<int> myNullableInteger;

à

int? myNullableInteger;

Le compilateur empêchera d'essayer 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 empêche l'une de le faire car le type de valeur Nullable peut 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 autoriserait ce code,

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

La deuxième instruction entraînerait une exception à être levée 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 une valeur valide de T, ce qui n'est pas le cas dans cette 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 déterminer 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 est assigné à la valeur de l'entier nullable "myNullableInteger" si on lui a assigné une valeur entière valide; sinon, myInteger reçoit la valeur -1.


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

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

se développe pour:

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

qui s'étend à:

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 lequel de ces nombres en séquence. L'instruction suivante affectera la première Answer# à la Answer non nulle (si toutes les réponses sont nulles, la Answer est nulle):

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

Aussi, il vaut la peine 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. (Merci à @Joey pour l'avoir signalé.)


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

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

dans l'objet:

? anArgument
    ^ self

dans UndefinedObject (la classe de nil):

? anArgument
    ^ anArgument

Il existe à la fois des versions d'évaluation (?) Et de non-évaluation (??).
Il est souvent trouvé dans les méthodes getter pour les variables privées (instance) paresseuses initialisées, qui sont laissées nuls jusqu'à ce que vraiment nécessaire.


C'est un opérateur de coalescence nulle qui fonctionne de manière similaire à un opérateur ternaire.

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

Un autre point intéressant est "Un type NULL peut contenir une valeur, ou il peut être indéfini" . Ainsi, 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 faire cela en utilisant ?? opérateur:

z = x ?? 1; // with ?? operator there are no issues

Certains des exemples ici d'obtenir des valeurs en utilisant 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 requête, cela garantit que la variable privée est assignée si le nouvel objet est créé.


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;

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;

Comme correctement souligné dans de nombreuses réponses qui est l'opérateur de coalescence nulle ( ?? ), en parlant de laquelle vous pourriez aussi vouloir vérifier son cousin le "Opérateur Null-conditionnel" ( ?. Ou ? [ ) Qui est un opérateur qui plusieurs fois, il est utilisé en conjonction avec ??

Opérateur null-conditionnel

Utilisé pour tester 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 vérifications nuls, en particulier pour descendre dans des 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 façon 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 lourd.


opérateur de coalescence

c'est équivalent à

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

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

est équivalent à

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

Mais la chose cool à ce sujet est que vous pouvez les enchaîner, comme d'autres personnes l'ont dit. Celui qui n'est pas touché est que vous pouvez l'utiliser pour lancer une exception.

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


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

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 démontre le tout pratiquement.

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

Si vous voyez le sens anglais de la coalescence, il est dit "consolider ensemble". Par exemple ci-dessous est un simple code de coalescence qui enchaîne quatre chaînes.

Donc, si str1 est null il essayera str2 , si 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 ternaire:

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






null-coalescing-operator