Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics and challenges on the Parser Front

Tags:

c#

generics

If you have:

F(G<A,B>(4));

does this mean that the user wants to call a method F with 2 parameters that result from comparing G and A, and B and the constant 4?

Or does it mean call F with the result of calling generic method G using type parameters A and B and an argument of 4?

like image 220
David Klempfner Avatar asked Aug 06 '13 04:08

David Klempfner


2 Answers

So I tried it out just to be sure. It turns out this works just fine:

void F(int x) { }
int G<T, U>(int x) { return x; }

class A { }
class B { }

void Main()
{
    F(G<A,B>(4));
}

But this produces a number of compile errors:

void F(bool x, bool y) { }

void Main()
{
    int G = 0, A = 1, B = 2;
    F(G<A,B>(4));
}

The type or namespace name 'A' could not be found (press F4 to add a using directive or assembly reference)

The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?)

The variable 'G' is not a generic method. If you intended an expression list, use parentheses around the < expression.

So the answer is that the expression F(G<A,B>(4)) is interpreted as a generic function call. There are any number of ways to force the compiler to treat this as a single function call of two parameters: F(G<A,B>4), F((G)<A,B>(4)), or F(G>A,B>(4)), just to name a few.

like image 98
p.s.w.g Avatar answered Nov 15 '22 14:11

p.s.w.g


You should read 7.6.4.2 of the C# spec, which deals with grammar ambiguities and discusses this example almost verbatim. To quote:

If a sequence of tokens can be parsed (in context) as a simple-name (§7.6.2), member-access (§7.6.4), or pointer-member-access (§18.5.2) ending with a type-argument-list (§4.4.1), the token immediately following the closing > token is examined. If it is one of

( ) ] } : ; , . ? == != | ^

then the type-argument-list is retained as part of the simple-name, member-access or pointer-member-access and any other possible parse of the sequence of tokens is discarded.

Here, G is a simple-name and the question is whether <A,B> is to be interpreted as a type-argument-list as part of this simple name.

There is a ( after the >, so the fragment G<A,B> is the simple-name of a method. The method is a generic method with type arguments A and B and an argument of 4. F is therefore a method with a single parameter.

One interesting thing to note is that this is a case where the compiler does not consider any alternatives if parsing fails. As you can see from p.s.w.g.'s answer, even if the only valid interpretation is one where F is a method that takes two parameters, it is not considered.

like image 45
Mike Zboray Avatar answered Nov 15 '22 13:11

Mike Zboray