Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are the methods groups allowed on the left-side of ‘is’ operator and how can this be used in practice?

First of all “A method group is a set of overloaded methods resulting from a member lookup”. In my example I use the set of Console.WriteLine methods with 19 overloads.

The definition of a method group in C# Language Specification also states that: “A method group is permitted in an invocation-expression (§7.6.5) , a delegate-creation-expression (§7.6.10.5) and as the left hand side of an is operator, and can be implicitly converted to a compatible delegate type (§6.6).”

I could think of one scenario where this functionality could be useful:

Action<string> print = (Action<string>)Console.WriteLine;
print("Hello!");

if (Console.WriteLine is Action<string>) 
{
    Console.WriteLine("We're compatible!");
}

First couple of lines show that we can ‘cast’ a method group Console.WriteLine into a delegate. What actually happens is the “implicit conversion converted to a compatible delegate type”, which creates an instance of a delegate calling one of many overloaded Console.WriteLine methods with compatible signature.

So according to specs we could use the “left side of is operator” feature mentioned above to test if the method group is compatible with a given delegate type (implicit conversion exists). This is what is checked inside the ‘if’ statement in the sample code.

Surprisingly, the code compiles, but gives a warning “The given expression is never of the provided ('System.Action') type”. So it looks like there will be no attempts to check the compatibility of the method group and the delegate type at runtime.

Hence, my questions:

  • Why are the methods groups allowed on the left-side of ‘is’ operator if the check cannot be performed at runtime?
  • Why this construct gives a warning and not a compilation error?
  • Are there any practical scenarios of using method groups on the left side of ‘is’ operator?
  • Is this something reserved for future uses, i.e. it is envisaged that the code above will work someday?
like image 521
Nicol Eye Avatar asked Aug 30 '15 15:08

Nicol Eye


1 Answers

The specification (4.0) explicitly calls out this specific case:

7.10.10 The is operator

[...] The result of the operation E is T where E is an expression and T is a type, is a boolean value [...]

So far, so good. The specification continues:

If E is a method group [...] the result is false.

Given this information, let's look at your questions.

Why are the methods groups allowed on the left-side of ‘is’ operator if the check cannot be performed at runtime?

The specification allows for this operation. See Lippert's answer on another question about how this came to be.

Why this construct gives a warning and not a compilation error?

The construct is syntactically valid, even though it always evaluates to false. The warning is just there to let you know that you may be doing something unintended.

Are there any practical scenarios of using method groups on the left side of ‘is’ operator?

Probably not. Maybe if you were passed an object that may be a method group or may be something else this construct could be useful. (It's admittedly a contrived example, that represents some seriously questionable practices.)

Is this something reserved for future uses, i.e. it is envisaged that the code above will work someday?

No. Quoting again from Lippert "it would be a breaking change to make 'M is D' suddenly start returning true or being an error." [Emphasis in original]

like image 104
theB Avatar answered Oct 16 '22 22:10

theB