Supponiamo che vi troviate davanti a un quiz come questo:
class Foo
{
static void Main()
{
string s1 = string.Empty;
string s2 = "";
double d = System.Math.PI;
}
}
Secondo voi, quanti warning "The variable 'variable' is assigned but its value is never used" otterreste in compilazione? Qualcuno dirà 3, un altro 2, un altro ancora 1, mentre i più fighi diranno nessuno. La risposta però è 2. Per capire il motivo non mi sono stati d'aiuto né le specifiche, nè Richter, né Box, né Gunnerson. La risposta l'ho trovata spulciando nel Rotor, nel corpo dei metodi FUNCBREC::reportUnreferencedVars (le righe 668-683) e FUNCBREC::bindAssignment (le righe 7488-7533). Vediamo cosa ho capito.
Per ottenere in un'assegnazione a = b il nostro warning, WRN_UnreferencedVarAssg, lo slot (un campo di tipo LOCSLOTINFO) di a deve avere i 3 seguenti campi simultaneamente impostati così:
- isReferenced impostato a false;
- isParam impostato a false;
- IsReferencedAssg impostato a true.
Nel nostro caso, isParam è già false perché la nostra variabile è una variabile locale e non un parametro. Vediamo gli altri due: isReferenced e isReferencedAssg. Determinante per il nostro warning è se l'espressione b sia un'espressione costante o no (per una definizione delle espressioni costanti, leggere le specifiche, il paragrafo 14.15). Perché questo? Perché nel corpo della funzione FUNCBREC::bindAssignment, nel caso in cui b non sia un'espressione costante, si richiama subito il metodo noteReference (le righe 7417-7424 nel file fncbind.cpp) che imposta isReferenced dello slot di a a true se a è una variabile locale (il nostro caso) o un campo. Quindi, quando b NON è un'espressione costante, il warning non si ottiene! Invece, nel caso lo fosse, con a variabile locale, isReferencedAssg viene impostato a true e da qui deriva il warning.
Nel quiz sopra, System.Math.PI è una costante, così come "", ma System.String.Empty è un campo static readonly, perciò per s1 non otteniamo warning.
Quiz bastardo... Secondo voi è un comportamento corretto?