I already know that the null-conditional operator can be used to test for null before performing a member access.
for example :
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0];
If customers
is null in customers?.Length
, then customers?.Length
will return null and that null
will be in int? length = ...
variable
I also know that it can be used for a single atomic operation of method invocation in a multithreaded environment :
public void OnFoo()
{
Foo?.Invoke(this, EventArgs.Empty);
}
But
AFAIU - if Foo
is null
then
Foo?.Invoke(this, EventArgs.Empty);
Is also null
And so we're left with
public void OnFoo()
{
null; //compilation error
}
And so I ask :
Question
it seems that the null-conditional operator is not only for testing null and if there is , then it moves on deeper : x?.y?.c?.d
-
but it is also act like code toggle :
Like this:
public void OnFoo()
{
Foo?.Invoke(this, EventArgs.Empty); //Let's assume Foo =null;
}
Becomes
public void OnFoo()
{
}
Am I right? I didn't find any documentation to that aspect.
The null conditional operator is an operator which results in an expression - it's not a statement.
Your logic about Foo?.Invoke(this, EventArgs.Empty)
being equivalent to null
doesn't really hold, as it seems to assume a sort of "template replacement" which doesn't apply.
The type of the expression
Foo?.Invoke(this, EventArgs.Empty)
is nothing, because Invoke
has a void
return type. You can't write:
// Invalid
var result = Foo?.Invoke(this, EventArgs.Empty);
This is just like in 7.6.5 of the C# 5 specification:
The result of evaluating an invocation-expression is classified as follows:
- If the invocation-expression invokes a method or delegate that returns
void
, the result is nothing. An expression that is classified as nothing is permitted only in the context of a statement-expression (§8.6) or as the body of a lambda-expression (§7.15). Otherwise a binding-time error occurs.- Otherwise, the result is a value of the type returned by the method or delegate.
A member invocation can use a null conditional operator, at which point the invocation is only performed when the primary expression evaluates to a non-null value. The result of an invocation expression involving a null conditional operator is the same as it would be with a regular .
operator, except that if the result would be a non-nullable value type, the result with the null conditional operator is the corresponding nullable value type.
All of this will be put a lot more precisely when the C# 6 specification comes out, of course - but I don't know when that will be. (I don't think there's a C# 6 spec at the moment. I'm sure there's one internally in MS, but not a public one. As the ECMA standardization process is getting closer for standardizing C# 5, that could potentially impact the release process for C# 6.)
See more on this question at Stackoverflow