Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C# require parentheses when using nullables in an expression?

Tags:

c#

nullable

I'm new to C# and while exploring the language features, I came across something strange:

struct Foo
{
    public Foo Identity() { return this; }

    public static void Bar(Foo? foo)
    {
        Foo foo1 = foo?.Identity().Value; // Does not compile
        Foo foo2 = (foo?.Identity()).Value; // Compiles
    }
}

Could anyone explain to me why the parenthesis are needed?

like image 848
Lukas92 Avatar asked Jul 05 '16 14:07

Lukas92


People also ask

Why does letter C exist?

Like the letter G, C emerged from the Phoenician letter gimel (centuries later, gimel became the third letter of the Hebrew alphabet). In ancient Rome, as the Latin alphabet was being adapted from the Greek and Etruscan alphabets, G and C became disambiguated by adding a bar to the bottom end of the C.

Does the letter C need to exist?

So the C is indeed a very important letter and has no reason to feel ashamed because it makes no sound on it own. Like a man and a women come together to make a unique "sound" in their marriage, so "C" marries "H" to produce a special combined sound. CH itself has three different sounds.

Why is C named so?

Quote from wikipedia: "A successor to the programming language B, C was originally developed at Bell Labs by Dennis Ritchie between 1972 and 1973 to construct utilities running on Unix." The creators want that everyone "see" his language. So he named it "C".

Why does C make two sounds?

In the Latin-based orthographies of many European languages, including English, a distinction between hard and soft ⟨c⟩ occurs in which ⟨c⟩ represents two distinct phonemes. The sound of a hard ⟨c⟩ often precedes the non-front vowels ⟨a⟩, ⟨o⟩ and ⟨u⟩, and is that of the voiceless velar stop, /k/ (as in car).


1 Answers

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() returns Foo, why does Foo foo3 = foo?.Identity(); not compile ?

The equivalent of that would be:

Foo foo3
if(foo != null)
{
    foo3 = foo.Identity();
}
else
{
    foo3 = null;  // not possible 
}
like image 117
D Stanley Avatar answered Oct 22 '22 21:10

D Stanley