Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Language Design: method group inside `is` operator

I'm interesting in some design choices of C# language. There is a rule in C# spec that allows to use method groups as the expressions of is operator:

class Foo {   static void Main() { if (Main is Foo) Main(); } } 

Condition above is always false, as the specification says:

7.10.10 The is operator

If E is a method group or the null literal, of if the type of E is a reference type or a nullable type and the value of E is null, the result is false.

My questions: what is the purpose/point/reason of allowing to use the C# language element with no runtime representation in CLR like method groups inside the such "runtime" operator like is?

like image 601
controlflow Avatar asked Jul 12 '10 20:07

controlflow


2 Answers

what is the purpose/point/reason of allowing to use the C# language element with no runtime representation in CLR like method groups inside the such "runtime" operator like is?

The language design notes archive make no mention of why this decision was made, so any guess at an answer will be a conjecture. They do mention that if the result of the "is" can be statically determined to always be true or false, that it be so determined and produce a warning. It seems plausible that this could simply be an error.

The most common reason for turning what could rightly be an error into a warning (or simply allowing it) is because that lessens the burden upon producers of programs that automatically generate code. However, I don't see a really compelling scenario here.

UPDATE:

I just checked the C# 1.0 specification. It does not have this language in it. It does not say anything about nulls or method group arguments. And of course it says nothing about method group conversions because in C# 1.0 there were no implicit method group conversions; you had to explicitly call "new D(M)" if you wanted to convert method M to delegate type D.

This latter point is justification for "M is D" returning false rather than true; You couldn't legally say "D d = M;" so why should "M is D" be true?

Of course in C# 2.0 this makes less sense, since you can say "D d = M;" in C# 2.0.

I also just asked one of the people present when the "is" operator was designed and he had no memory of ever deciding this question one way or the other. His suspicion was that the original design of the "is" operator was to not give any errors, only warnings, and that all the text in the spec about what to do with method groups and nulls and whatnot was added post-hoc, for the C# 2.0 version of the spec, and based on what the compiler actually did.

In short, it looks like this was a design hole in C# 1.0 that was papered over when the spec was updated for C# 2.0. It does not look like this specific behaviour was desired and deliberately implemented.

This theory is reinforced by the fact that anonymous methods do produce an error when used as an argument to "is" in C# 2.0. It would not be a breaking change to do so, but it would be a breaking change to make "M is D" suddenly start returning true or being an error.

FURTHER UPDATE:

While investigating this I learned something interesting. (To me.) When the feature was originally designed, the design was to allow either the name of a type, or a Type object as the right-hand argument to "is". That idea was abandoned well before C# 1.0 shipped though.

like image 53
Eric Lippert Avatar answered Sep 28 '22 09:09

Eric Lippert


First of all a method is not a type, msdn clearly states the following:

The is operator is used to check whether the run-time type of an object is compatible with a given type

Example

public static void Test (object o)  {    Class1 a;     if (o is Class1) {} } 

From MSDN:

An is expression evaluates to true if both of the following conditions are met:

  • expression is not null.
  • expression can be cast to type. That is, a cast expression of the form (type)(expression) will complete without throwing an exception. For more information, see 7.6.6 Cast expressions.

So the reason for your example being false lands on the second point, it has to be castable to a specific type.

I hope I did not missunderstand the question.

like image 33
Filip Ekberg Avatar answered Sep 28 '22 09:09

Filip Ekberg