2009-05-05 8 views

risposta

38

Eric Lippert ha fatto un intero post sul blog sull'argomento.

In sintesi, il problema principale è che avrebbe richiesto un importante ri-architettura del compilatore C# per farlo. Le dichiarazioni vengono attualmente elaborate in un unico passaggio. Ciò richiederebbe più passaggi a causa della possibilità di creare cicli tra variabili dedotte. VB.net ha grosso modo lo stesso problema.

+0

divertente, egli propone di aggiungere un altro elemento alla lingua solo per compensare un deficit del compilatore. Esistono modi per scrivere un compilatore che non consente la fuoriuscita di tipi anonimi o che può gestire un approccio di primo passaggio posticipato. –

+5

Sono consapevole che ci sono modi per farlo. Stiamo scegliendo di non fare nessuno di questi in questo momento; i loro costi non valgono i benefici. –

+0

scusa Eric, immagino che tutto quello che sto cercando di dire è che sono felice di aspettare il refattore del compilatore invece di votare per copiare java's new(), anche se possiamo farlo prima. Semplicemente non mi sembra adatto perché abbiamo già var. –

0

Penso che sia perché la portata di tale tipo implicita è molto più ampia e quindi più probabilità di causare problemi rispetto nell'ambito di un unico metodo.

1

Perché è molto più facile da fare. Se dovessi dedurre tutti i tipi, occorrerebbe qualcosa come il sistema di inferenza di tipo Hindley Milner che renderà il tuo amato C# nel linguaggio derivato Haskel.

1

In sostanza, il problema si esegue in è che C# (finora) è un linguaggio a tipizzazione statica. Una variabile locale definita come var è ancora tipizzata staticamente, ma sintatticamente nascosta. Un metodo che restituisce var, d'altra parte, ha molte implicazioni. Diventa più un'interfaccia per l'utilizzo e non si guadagna nulla usando var.

6

Jared ha una fantastica link nella sua risposta, ad un argomento fantastico.

penso che non risponde alla domanda in modo esplicito.

Perché no?

var getFoo() { 
    return new Foo(); 
} 

La ragione di questo è:

What if?

class Foo {} 

var GetFoo() { 
    return GetBar(); 
} 

var GetBar() { 
    return GetBaz(); 
} 

var GetBaz() { 
    return new Foo(); 
} 

Si potrebbe dedurre che GetFoo sta per tornare Foo, ma si dovrà tracciare attraverso tutti le chiamate che il metodo fa e le sue bambini fa solo per dedurre il tipo. Così com'è, il compilatore C# non è progettato per funzionare in questo modo. Ha bisogno di metodi e tipi di campo nelle prime fasi del processo prima del codice che può essere utilizzato dai tipi.

Su un piano puramente estetico trovo le definizioni var sui metodi di confondere le cose. Il suo unico posto dove penso che sia esplicito sempre aiuta, ti protegge dal spararti nel piede restituendo per sbaglio un tipo che causa la tua firma e una tonnellata di altre firme del metodo dipendente da modificare. Peggio ancora, potresti potenzialmente cambiare tutte le firme di una catena di metodi senza nemmeno sapere che lo hai fatto se restituisci il valore di un metodo che restituisce un oggetto e che è stato fortunato.

Penso metodi var è meglio lasciarle per linguaggi dinamici come Ruby

+11

No, non è questo il problema. Abbiamo già risolto il problema in C#, come puoi dimostrare. Se fai getFoo in un lambda, dedurremo il tipo di ritorno del lambda come Foo. Tuttavia ci sono problemi reali. Un problema è cosa succede se "var getFoo() {...}" chiama "var getBar() {...}" che a sua volta chiama ... si finisce per dover potenzialmente eseguire l'analisi dell'intero programma solo per digitare il metodi. L'attuale architettura del compilatore presuppone che i metodi e i campi possano essere digitati prima che i corpi del metodo vengano analizzati. –

+0

Risposta corretta ed estesa per riflettere –

1

è possibile utilizzare in vs 2010 dinamica

Dynamic getFoo() { 
    return new Foo(); 
} 
+0

A meno che letteralmente non sia possibile scrivere il tipo lì (ad esempio, i tipi anonimi), questo è un modo orribile per evitare di scrivere nomi di caratteri lunghi. Butti via tutti i vantaggi (piuttosto considerevoli) del legame statico. –

+0

Ma è 'dinamico', in minuscolo –

+0

Questo è molto utile! Questo risolve tutti i casi ovvi in ​​cui ho bisogno di un campo per avere il suo tipo inferito dall'inizializzatore, che è molto per me. E Eric L. ha detto lo stesso diritto all'inizio del suo lavoro spiegando perché non var per i campi. Il suo intervento prosegue spiegando come i casi estremi ricorsivi siano un problema, ma non riuscivo a capire perché il caso più comune non fosse affrontato. Per fortuna "dinamico" risolve questo problema. –