2017-01-20 4 views
4

J'attire spécifiquement l'attention sur la propagation de zéro en ce qui concerne bool? et l'utilisation d'une méthode de retour bool. Par exemple, considérer les points suivants:Pourquoi la propagation de type NULL se produit de manière incohérente Nullable <T>?

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any(); 
} 

Cela ne compile pas, et l'erreur suivante existe:

ne peut pas convertir implicitement bool? booler. Une conversion explicite existe (manque-t-il une distribution)?

Cela implique qu'il traite le corps entier de la méthode comme bool?, en tant que tel, je suppose que je pourrais dire .GetValueOrDefault() après la .Any() mais ce n'est pas autorisé comme .Any() retours bool pas bool?.

Je sais que je pouvais faire une des opérations suivantes comme une œuvre autour de:

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any() 
     ?? false; 
} 

Ou

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    var any = 
     property?.AttributeProvider 
       .GetAttributes(typeof(TAttribute), false) 
       .Any(); 

    return any.GetValueOrDefault(); 
} 

Ou

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any() 
     ?? false; 
} 

Ma question est, pourquoi je ne peux pas invoquer directement .GetValueOrDefault() enchaînement sur l'invocation .Any()?

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute 
{ 
    return (property?.AttributeProvider 
        .GetAttributes(typeof(TAttribute), false) 
        .Any()) 
        .GetValueOrDefault(); 
} 

Je pense que ce serait logique que la valeur est en fait bool? à ce stade et non bool.

+1

Vous devriez mettre entre parenthèses, donc 'opérateur .' connu, où la chaîne d'appel état termine: '(propriété? .AttributeProvider.GetAttributes (typeof (TAttribute), false) .Any()). GetValueOrDefault()'. – PetSerAl

+0

Si 'propriété' est null, la méthode tentera de retourner null. Cependant, il ne peut pas parce que le type de retour est 'bool', qui n'est pas un type nullable. Changez le type de retour en 'bool?'. – Abion47

Répondre

5

Après l'opérateur ?., la chaîne d'appel est interprétée comme un appel conditionnel non seulement immédiat. Ainsi, ce code:

property?.AttributeProvider 
     .GetAttributes(typeof(TAttribute), false) 
     .Any() 

interprété comme

property==null ? (bool?)null : property.AttributeProvider 
             .GetAttributes(typeof(TAttribute), false) 
             .Any() 

Si vous ajoutez GetValueOrDefault():

property==null ? (bool?)null : property.AttributeProvider 
             .GetAttributes(typeof(TAttribute), false) 
             .Any() 
             .GetValueOrDefault() 

il échouera, car Any() retour bool pas bool?.Ainsi, vous devez utiliser des parenthèses ici:

(property==null ? (bool?)null : property.AttributeProvider 
             .GetAttributes(typeof(TAttribute), false) 
             .Any()) 
             .GetValueOrDefault() 

parenthèses Même vous devez utiliser lorsque vous utilisez l'opérateur ?.:

(property?.AttributeProvider 
      .GetAttributes(typeof(TAttribute), false) 
      .Any()) 
      .GetValueOrDefault() 
2

L'appel GetValueOrDefault s'exécute sur le retour de la méthode Any(), qui renvoie un bool. Si vous voulez exécuter sur le résultat de l'ensemble du corps, vous devez l'envelopper entre parenthèses.

return (property?.AttributeProvider 
       .GetAttributes(typeof(TAttribute), false) 
       .Any()) 
       .GetValueOrDefault(); 

L'opérateur conditionnel nul est un opérateur court-circuit et donc tout à la droite du point qui tente d'exécuter sur l'objet ou les propriétés ou les méthodes ne seront pas exécutées si l'objet est nul. Ainsi, pour exécuter du code sur l'ensemble de l'instruction, vous devez l'enrouler d'une certaine façon (entre parenthèses ou en utilisant un autre objet).

+0

Je sais que je peux vous des parenthèses. Mais ce n'est pas ce que je demande. C# traite l'énoncé entier comme «bool?», Mais je ne peux pas agir comme s'il s'agissait d'un «bool?». Je sais ce qu'il fait, je demande pourquoi. –