Could anyone explain to me why the parenthesis are needed?
Because Identity() returns a Foo (not a Foo?) and thus has no Value property. If foo is null, the null will propagate through the Identity call.
When you put parentheses around it, the results of the expression is a Nullable<Foo> which does have a Value property.
Also note that if foo is null, then you will be calling Value on a Nullable<Foo> that has no value, and will get an exception at run-time. Some static analyzers will recognize that you have a possible null-reference exception waiting to happen and warn you.
If you expand them to their equivalents without null-propagation it will be more clear:
Foo foo1;
if(foo != null)
{
foo1 = foo.Identity().Value; // not possible - Foo has no Value property.
}
else
{
foo1 = null; // also not possible
}
Foo foo2;
Foo? temp;
if(foo != null)
{
temp = foo.Identity();
}
else
{
temp = null; // actually a Nullable<Foo> with no value
}
foo2 = temp.Value; // legal, but will throw an exception at run-time if foo is null
If
Identity()returnsFoo, why doesFoo foo3 = foo?.Identity();not compile ?
The equivalent of that would be:
Foo foo3
if(foo != null)
{
foo3 = foo.Identity();
}
else
{
foo3 = null; // not possible
}