I'm specifically calling attention to null-propagation as it pertains to bool?
and the use of a bool
returning method. For example, consider the following:
public static bool IsAttributedWith<TAttribute>(this JsonProperty property)
where TAttribute : Attribute
{
return property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any();
}
This doesn't compile, and the following error exists:
Cannot implicitly convert bool? to bool. An explicit conversion exists (are you missing a cast)?
This implies that it is treating the entire body of the method as a bool?
, as such I would assume that I could say .GetValueOrDefault()
after the .Any()
but this is not allowed as .Any()
returns bool
not bool?
.
I know that I could do either of the following as a work around:
public static bool IsAttributedWith<TAttribute>(this JsonProperty property)
where TAttribute : Attribute
{
return property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any()
?? false;
}
Or
public static bool IsAttributedWith<TAttribute>(this JsonProperty property)
where TAttribute : Attribute
{
var any =
property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any();
return any.GetValueOrDefault();
}
Or
public static bool IsAttributedWith<TAttribute>(this JsonProperty property)
where TAttribute : Attribute
{
return property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any()
?? false;
}
My question is, why can I not directly invoke .GetValueOrDefault()
chaining on the .Any()
invocation?
public static bool IsAttributedWith<TAttribute>(this JsonProperty property)
where TAttribute : Attribute
{
return (property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any())
.GetValueOrDefault();
}
I think this would make sense as the value is actually bool?
at this point and not bool
.
After ?.
operator all following call chain interpreted as conditional not only immediate call. So, this code:
property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any()
interpreted as
property==null ? (bool?)null : property.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any()
If you add GetValueOrDefault()
:
property==null ? (bool?)null : property.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any()
.GetValueOrDefault()
it will fail, because Any()
return bool
not bool?
. Thus you need to use parenthesis here:
(property==null ? (bool?)null : property.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any())
.GetValueOrDefault()
Same parenthesis you need to use when you use ?.
operator:
(property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any())
.GetValueOrDefault()
The GetValueOrDefault
call is executing on the return of the Any()
method, which returns a bool
. If you want to execute on the result of the whole body, you would have to wrap it in parentheses.
return (property?.AttributeProvider
.GetAttributes(typeof(TAttribute), false)
.Any())
.GetValueOrDefault();
The null conditional operator is a short circuiting operator and thus anything to the right of the dot that is attempting to execute on the object or any its properties or methods will not be executed if the object is null. So, in order to execute code on the whole statement, you must wrap it some way (parentheses or using another object).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With