una - var c#




Uso della parola chiave var in C# (20)

Abbiamo adottato l'ethos "Codice per le persone, non le macchine", basato sul presupposto che si spende più volte più a lungo in modalità di manutenzione che in un nuovo sviluppo.

Per me, questo esclude l'argomento secondo il quale il compilatore "sa" di che tipo è la variabile - certo, non è possibile scrivere codice non valido la prima volta perché il compilatore interrompe la compilazione del codice, ma quando il prossimo sviluppatore sta leggendo il codice in 6 mesi devono essere in grado di dedurre ciò che la variabile sta facendo correttamente o in modo errato e identificare rapidamente la causa dei problemi.

Così,

var something = SomeMethod();

è vietato dai nostri standard di codifica, ma nel nostro team viene incoraggiato quanto segue perché aumenta la leggibilità:

var list = new List<KeyValuePair<string, double>>();
FillList( list );
foreach( var item in list ) {
   DoWork( item ); 
}

Dopo una discussione con i colleghi sull'uso della parola chiave 'var' in C # 3 mi sono chiesto quali erano le opinioni delle persone sugli usi appropriati dell'inferenza di tipo tramite var?

Ad esempio, ho usato pigramente var in circostanze discutibili, ad esempio: -

foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.

Altri usi legittimi di var sono i seguenti: -

var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.

È interessante notare che LINQ sembra essere un po 'un'area grigia, ad esempio: -

var results = from r in dataContext.SomeTable
              select r; // Not *entirely clear* what results will be here.

È chiaro quali saranno i risultati in quanto sarà un tipo che implementa IEnumerable, tuttavia non è del tutto ovvio nello stesso modo in cui una var che dichiara un nuovo oggetto è.

È ancora peggio quando si tratta di LINQ per oggetti, ad esempio: -

var results = from item in someList
              where item != 3
              select item;

Questo non è migliore del foreach equivilent (var item in someList) {// ...} equivilent.

C'è una vera preoccupazione per la sicurezza del tipo qui - per esempio se dovessimo collocare i risultati di quella query in un metodo sovraccarico che accettasse IEnumerable <int> e IEnumerable <double> il chiamante potrebbe inavvertitamente passare nel tipo sbagliato.

var mantiene una forte digitazione, ma la domanda è davvero se sia pericoloso che il tipo non sia immediatamente evidente alla definizione, qualcosa che viene ingrandito quando sovraccarichi significano errori del compilatore potrebbero non essere emessi quando si passa involontariamente il tipo sbagliato a un metodo.


Continuo a pensare che var possa rendere il codice più leggibile in alcuni casi. Se ho una classe Customer con una proprietà Orders e desidero assegnarla a una variabile, lo farò semplicemente:

var orders = cust.Orders;

Non mi interessa se Customer.Orders è IEnumerable<Order> , ObservableCollection<Order> o BindingList<Order> - tutto quello che voglio è mantenere la lista in memoria per iterare su di essa o ottenere il suo conteggio o qualcosa in seguito.

Contrastare la dichiarazione di cui sopra con:

ObservableCollection<Order> orders = cust.Orders;

Per me, il nome del tipo è solo rumore. E se torno indietro e decido di cambiare il tipo di Customer.Orders in fondo alla traccia (ad esempio da ObservableCollection<Order> a IList<Order> ) allora ho bisogno di cambiare anche quella dichiarazione - qualcosa che non avrei dovuto fare se Avevo usato var in primo luogo.


Dato quanto sia potente Intellisense ora, non sono sicuro che var sia più difficile da leggere rispetto ad avere variabili membro in una classe, o variabili locali in un metodo che è definito al di fuori dell'area dello schermo visibile.

Se hai una riga di codice come

IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

È molto più facile o più difficile da leggere rispetto a:

var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

Il tempo più probabile di cui avrai bisogno è per i tipi anonimi (dove è richiesto al 100%); ma evita anche la ripetizione per i casi banali, e IMO rende la linea più chiara. Non ho bisogno di vedere il tipo due volte per una semplice inizializzazione.

Per esempio:

Dictionary<string, List<SomeComplexType<int>>> data = new Dictionary<string, List<SomeComplexType<int>>>();

(per favore non modificare l'hscroll nel precedente - è un po 'la prova del punto !!!)

vs:

var data = new Dictionary<string, List<SomeComplexType<int>>>();

Ci sono, tuttavia, occasioni in cui questo è fuorviante e può potenzialmente causare bug. Prestare attenzione all'utilizzo di var se la variabile originale e il tipo inizializzato non erano identici. Per esempio:

static void DoSomething(IFoo foo) {Console.WriteLine("working happily") }
static void DoSomething(Foo foo) {Console.WriteLine("formatting hard disk...");}

// this working code...
IFoo oldCode = new Foo();
DoSomething(oldCode);
// ...is **very** different to this code
var newCode = new Foo();
DoSomething(newCode);

Nessuno di questi è assolutamente vero; var può avere effetti sia positivi che negativi sulla leggibilità. Secondo me, var dovrebbe essere usato quando si verifica una delle seguenti condizioni:

  1. Il tipo è anonimo (beh, non hai alcuna scelta qui, in quanto deve essere var in questo caso)
  2. Il tipo è ovvio in base all'espressione assegnata (ad es. var foo = new TypeWithAReallyLongNameTheresNoSenseRepeating() )

var non ha impatti sulle prestazioni, in quanto è zucchero sintattico; il compilatore deduce il tipo e lo definisce una volta compilato in IL; non c'è nulla di dinamico in questo.


Non è male, è più una cosa stilistica, che tende ad essere soggettiva. Può aggiungere incongruenze, quando usi var e quando non lo fai.

Un altro caso di preoccupazione, nella seguente chiamata non si può dire solo guardando il codice del tipo restituito da CallMe :

var variable = CallMe();

Questo è il mio principale reclamo contro var.

Io uso var quando dichiaro delegati anonimi nei metodi, in qualche modo var sembra più pulito che se Func . Considera questo codice:

var callback = new Func<IntPtr, bool>(delegate(IntPtr hWnd) {
   ...
});

EDIT : aggiornato l'ultimo codice di esempio basato sull'input di Julian


Penso che l'uso di var dovrebbe essere accoppiato con nomi di variabili scelti con saggezza.

Non ho problemi ad usare var in un'istruzione foreach, a patto che non sia così:

foreach (var c in list) { ... }

Se fosse più simile a questo:

foreach (var customer in list) { ... }

... quindi qualcuno che legge il codice sarebbe molto più propenso a capire che cos'è "list". Se hai il controllo sul nome della variabile di lista stessa, è ancora meglio.

Lo stesso può valere per altre situazioni. Questo è abbastanza inutile:

var x = SaveFoo(foo);

... ma questo ha senso:

var saveSucceeded = SaveFoo(foo);

Ognuno al suo, immagino. Mi sono trovato a fare questo, che è solo folle:

var f = (float)3;

Ho bisogno di una sorta di programma var di 12 passi. Il mio nome è Matt, e io (ab) uso var.


Penso che la cosa fondamentale con VAR sia di usarla solo dove appropriato, cioè quando si fanno cose in Linq che facilita (e probabilmente in altri casi).

Se hai un tipo per qualcosa in poi dovresti usarlo - non farlo è semplice pigrizia (al contrario della pigrizia creativa che è generalmente da incoraggiare) - i bravi programmatori spesso lavorano molto per essere pigri e potrebbero essere considerati la fonte della cosa in primo luogo).

Un divieto generalizzato è tanto grave quanto abusare del costrutto in primo luogo, ma è necessario essere uno standard di codifica ragionevole.

L'altra cosa da ricordare è che non è un VB di tipo var in quanto non può cambiare tipo - è una variabile fortemente tipizzata è solo che il tipo è dedotto (che è il motivo per cui ci sono persone che sostengono che non è irragionevole per usarlo, per esempio, in una foreach, ma non sarei d'accordo per motivi di leggibilità e manutenibilità).

Sospetto che questo funzionerà e funzionerà (-:

Murph


Un caso specifico in cui var è difficile: recensioni di codici offline, in particolare quelli su carta.

Non puoi fare affidamento sui mouseover per questo.


Var non è affatto la variante. La variabile è ancora fortemente tipizzata, è solo che non si premono i tasti per ottenerlo in questo modo. Puoi passare il mouse su di esso in Visual Studio per vedere il tipo. Se stai leggendo il codice stampato, è possibile che tu debba pensare un po 'a capire di che tipo si tratta. Ma c'è solo una riga che la dichiara e molte linee che la usano, quindi dare dei nomi decenti è ancora il modo migliore per rendere il tuo codice più facile da seguire.

Sta usando Intellisense pigro? È meno digitante di tutto il nome. O ci sono cose che fanno meno lavoro ma non meritano critiche? Penso che ci sono, e var è uno di loro.


Io uso solo var quando è chiaro per vedere quale tipo viene utilizzato.

Ad esempio, vorrei usare var in questo caso, perché puoi vedere immediatamente che x sarà del tipo "MyClass":

var x = new MyClass();

NON userei var in casi come questo, perché devi trascinare il mouse sul codice e guardare il tooltip per vedere che tipo restituisce MyFunction:

var x = MyClass.MyFunction();

Soprattutto, non uso mai var nei casi in cui il lato destro non è nemmeno un metodo, ma solo un valore:

var x = 5;

(perché il compilatore non può sapere se voglio un byte, breve, int o altro)


Molte volte durante i test, mi trovo ad avere un codice come questo:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();
Console.WriteLine(something);

Ora, a volte, voglio vedere cosa contiene SomeOtherThing, SomeOtherThing non è lo stesso tipo restituito da CallMethod (). Dal momento che sto usando var però, ho appena cambiato questo:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();

a questo:

var something = myObject.SomeProperty.SomeOtherThing;

Senza var, dovrei continuare a cambiare il tipo dichiarato anche sul lato sinistro. So che è minore, ma è estremamente conveniente.


È una questione di gusti. Tutto questo agitarsi sul tipo di una variabile scompare quando ci si abitua a lingue digitate dinamicamente. Cioè, se mai inizi a piacergli (non sono sicuro che tutti possano farlo, ma lo faccio).

C # varè piuttosto interessante in quanto sembra una digitazione dinamica, ma in realtà è una tipizzazione statica - il compilatore applica l'uso corretto.

Il tipo di variabile non è così importante (è già stato detto prima). Dovrebbe essere relativamente chiaro dal contesto (le sue interazioni con altre variabili e metodi) e il suo nome - non aspettatevi che la lista clienti contenga un int...

Sto ancora aspettando di vedere cosa ne pensa il mio capo - ho avuto una coperta "vai avanti" per usare qualsiasi nuovo costrutto in 3.5, ma cosa faremo per la manutenzione?


@aku: un esempio sono le revisioni del codice. Un altro esempio è il refactoring di scenari.

Fondamentalmente non voglio andare a caccia del tipo con il mio mouse. Potrebbe non essere disponibile.


Ho diviso tutti i luoghi, gli unici posti discutibili per me sono i tipi brevi interni, ad esempio preferisco int i = 3;finitavar i = 3;


Immagino dipenda dalla tua prospettiva. Personalmente non ho mai avuto alcuna difficoltà a capire un pezzo di codice a causa di var"uso improprio", e i miei colleghi e io lo usiamo molto dappertutto. (Sono d'accordo sul fatto che Intellisense sia un enorme aiuto in tal senso.) Lo accolgo come un modo per rimuovere il ripetitivo cruft.

Dopo tutto, se affermazioni come

var index = 5; // this is supposed to be bad

var firstEligibleObject = FetchSomething(); // oh no what type is it
                                            // i am going to die if i don't know

erano davvero così impossibili da gestire, nessuno usava le lingue tipizzate dinamicamente.


Nel tuo confronto tra IEnumerable<int>e IEnumerable<double>non ti devi preoccupare - se passi il tipo sbagliato il tuo codice non verrà compilato comunque.

Non c'è preoccupazione per la sicurezza del tipo, poiché nonvar è dinamico. È solo magia del compilatore e qualsiasi tipo di chiamate non sicure che fai verrà catturato.

Var è assolutamente necessario per Linq:

var anonEnumeration =
    from post in AllPosts()
    where post.Date > oldDate
    let author = GetAuthor( post.AuthorId )
    select new { 
        PostName = post.Name, 
        post.Date, 
        AuthorName = author.Name
    };

Ora guarda anonEnumeration in intellisense e apparirà qualcosa di simileIEnumerable<'a>

foreach( var item in anonEnumeration ) 
{
    //VS knows the type
    item.PostName; //you'll get intellisense here

    //you still have type safety
    item.ItemId;   //will throw a compiler exception
}

Il compilatore C # è abbastanza intelligente - i tipi generati separatamente avranno lo stesso tipo generato se le loro proprietà corrispondono.

Al di fuori di questo, finché hai intellisenza, ha senso usare varovunque il contesto sia chiaro.

//less typing, this is good
var myList = new List<UnreasonablyLongClassName>();

//also good - I can't be mistaken on type
var anotherList = GetAllOfSomeItem();

//but not here - probably best to leave single value types declared
var decimalNum = 123.456m;


Per me, l'antipatia verso varillustra perché il bilinguismo in .NET è importante. Per quei programmatori C # che hanno anche fatto VB .NET, i vantaggi di varsono intuitivamente ovvi. La dichiarazione standard C # di:

List<string> whatever = new List<string>();

è l'equivalente, in VB .NET, di digitare questo:

Dim whatever As List(Of String) = New List(Of String)

Nessuno lo fa in VB .NET, però. Sarebbe stupido, perché sin dalla prima versione di .NET sei stato in grado di farlo ...

Dim whatever As New List(Of String)

... che crea la variabile e inizializza tutto in un'unica linea ragionevolmente compatta. Ah, ma cosa succede se vuoi un IList<string>, non un List<string>? Bene, in VB .NET questo significa che devi fare questo:

Dim whatever As IList(Of String) = New List(Of String)

Proprio come dovresti fare in C #, e ovviamente non potresti usare varper:

IList<string> whatever = new List<string>();

Se hai bisogno che il tipo sia qualcosa di diverso, può esserlo. Ma uno dei principi di base della buona programmazione sta riducendo la ridondanza, ed è esattamente ciò che fa var.


Rubato dal post su questo numero a CodingHorror :

Sfortunatamente, tu e tutti gli altri avete sbagliato. Mentre sono d'accordo con te che la ridondanza non è una buona cosa, il modo migliore per risolvere questo problema sarebbe stato di fare qualcosa di simile al seguente:

MyObject m = new ();

O se stai passando dei parametri:

Person p = new ("FirstName", "LastName);

Dove nella creazione di un nuovo oggetto, il compilatore deduce il tipo dal lato sinistro, e non dal lato destro. Questo ha altri vantaggi rispetto a "var", in quanto potrebbe essere utilizzato anche nelle dichiarazioni di campo (ci sono anche altre aree che potrebbero essere utili, ma qui non lo farò).

Alla fine, non era destinato a ridurre la ridondanza. Non fraintendetemi, "var" è MOLTO importante in C # per i tipi / proiezioni anonimi, ma l'uso qui è solo VERO (e lo sto dicendo da molto, molto tempo) mentre offuscate il tipo che viene usato. Dovere digitare due volte è troppo spesso, ma dichiararlo zero volte è troppo poco.

Nicholas Paldino .NET / C # MVP il 20 giugno 2008 08:00

Immagino che se la tua preoccupazione principale sia quella di dover digitare meno - allora non c'è nessun argomento che ti farà oscillare dall'usarlo.

Se si sta solo andando a mai essere la persona che guarda il tuo codice, quindi chi se ne frega? Altrimenti, in un caso come questo:

var people = Managers.People

va bene, ma in un caso come questo:

var fc = Factory.Run();

esso cortocircuita qualsiasi deduzione di tipo immediato che il mio cervello potrebbe iniziare a formare dall'inglese del codice.

Altrimenti, usa il tuo miglior giudizio e programmazione "cortesia" nei confronti di altri che potrebbero dover lavorare al tuo progetto.





var