Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it impossible to call static methods on Nullable<T> shorthands?

I thought T? is just a compiler shorthand for Nullable<T>. According to MSDN:

The syntax T? is shorthand for Nullable<T>, where T is a value type. The two forms are interchangeable.

However, there is a little (insignificant) difference: Visual Studio doesn't allow me to call static methods on shorthands:

bool b1 = Nullable<int>.Equals(1, 2); //no error
bool b2 = int?.Equals(1, 2); //syntax error "Invalid expression term 'int'"

Why? Is there any reason for this limitation?

like image 262
vojta Avatar asked May 31 '17 12:05

vojta


People also ask

Can we call static method on null object?

Very well you can call a static method with null object.

Why can't static methods call the instance methods present in the same class?

Within a static method, you do not have an instance of the class. So it will be impossible to call an instance method on an instance when no instance exists.

Can an instance call a static method?

Static methods can access the static variables and static methods directly. Static methods can't access instance methods and instance variables directly. They must use reference to object. And static method can't use this keyword as there is no instance for 'this' to refer to.

Can we access a static method of a class through null reference if yes how and if no why?

Yes. The compiler optimizes the code to invoke the static method using null object reference since object instance is not required to invoke a static method. In case of calling a non-static (instance) method using null object reference, it will throw NullPointerException.


1 Answers

Your MSDN quote echoes §4.1.10 of the C# 5.0 specification:

A nullable type is written T?, where T is the underlying type. This syntax is shorthand for System.Nullable<T>, and the two forms can be used interchangeably.

But “interchangeably” is an oversimplification. It’s true that T? means System.Nullable<T>, but as you’ve discovered, you can’t use T? everywhere that you can use System.Nullable<T>. In particular, the kind of member-access (§7.6.4) in your example requires a simple-name (§7.6.2):

[§7.6] Primary expressions include the simplest forms of expressions.

primary-expression:
  primary-no-array-creation-expression
  array-creation-expression

primary-no-array-creation-expression
  literal
  simple-name
  parenthesized-expression
  member-access
  ...

[§7.6.2] A simple-name is either of the form I or of the form I<A1, ..., AK>, where I is a single identifier and <A1, ..., AK> is an optional type-argument-list.

[§7.6.4] A member-access is either of the form E.I or of the form E.I<A1, ..., AK>, where E is a primary-expression, I is a single identifier and <A1, ..., AK> is an optional type-argument-list.

Nullable<T> is a simple-name and T? isn’t, so the former compiles whereas the latter doesn’t.

Why did the C# language designers require a member-access expression to use a simple-name as opposed to any type? I suppose only they can say for sure, but maybe this requirement simplified the grammar: In an expression, the compiler can assume that ? is always the conditional (ternary) operator instead of possibly a nullable type specifier.

In hindsight though, this was a fortunate choice that allowed C# 6.0 to add the ?. operator without possibly breaking existing programs. For example, consider this pathological example:

struct S
{
    public bool Equals(int x, int y) { return false; }
}

class C
{
    public static void Main()
    {
        S? S = new S();
        Console.WriteLine(S?.Equals(1, 1)); // "True" or "False"?
    }
}

Should S?.Equals be parsed as Nullable<S> . Equals, a call to the Equals static method of class Object? Or should it be parsed as S ?. Equals, a null-conditional call to the Equals instance method of variable S? Because S? isn’t a simple-name, it’s unambiguously the latter.

like image 55
Michael Liu Avatar answered Oct 16 '22 14:10

Michael Liu