2013-08-06 12 views
9

Se si dispone di:Generics e sfide sul Parser Fronte

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

Questo significa che l'utente vuole chiamare un metodo F con 2 parametri che risultano dal confronto fra G e A, e B e la costante 4 ?

O significa chiamare F con il risultato di chiamare il metodo generico G utilizzando i parametri di tipo A e B e un argomento di 4?

+3

Il secondo !, L'interno G (4) verrà elaborato prima, quindi verrà eseguita la chiamata per F() –

+0

La seconda, ovviamente, –

+0

perché pensi che sia il 2? –

risposta

7

Quindi l'ho provato solo per essere sicuro. Si scopre questo funziona bene:

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

class A { } 
class B { } 

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

Ma questo produce una serie di errori di compilazione:

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.

Quindi la risposta è che l'espressione F(G<A,B>(4)) viene interpretata come una chiamata di funzione generica. Esistono diversi modi per forzare il compilatore a considerarlo come una singola chiamata di due parametri: F(G<A,B>4), F((G)<A,B>(4)) o F(G>A,B>(4)), solo per citarne alcuni.

6

Si dovrebbe leggere 7.6.4.2 della specifica C#, che si occupa delle ambiguità grammaticali e discute questo esempio quasi alla lettera. Per citare:

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.

Qui, G è un semplice nome e la questione è se <A,B> deve essere interpretato come un tipo-argument-list come parte di questo semplice nome.

C'è un ( dopo il >, quindi il frammento G<A,B> è il nome semplice di un metodo. Il metodo è un metodo generico con argomenti di tipo A e B e un argomento di 4. F è quindi un metodo con un singolo parametro.

Una cosa interessante da notare è che questo è un caso in cui il compilatore non considera alcuna alternativa se l'analisi fallisce. Come si può vedere dalla risposta di p.s.w.g., anche se l'unica interpretazione valida è quella in cui F è un metodo che accetta due parametri, non viene considerato.