Cosa usare: var o tipo di nome oggetto? [duplicare]
-
04-07-2019 - |
Domanda
Questa domanda ha già una risposta qui:
- Uso della parola chiave var in C # 86 risposte
questa è una domanda che durante la programmazione mi chiedo sempre: cosa usare quando scriviamo il codice:
var myFiles = Directory.GetFiles(fullPath);
o
string[] myFiles = Directory.GetFiles(fullPath);
var è nuovo ed è un Variabili locali tipizzate in modo implicito , quindi possiamo usare solo localmente e ha regole che non possono essere null, ecc., ma mi chiedo se traiamo vantaggio dall'usarlo " normalmente " ;.
Il " normalmente " dice la parte, non in Tipi anonimi , inizializzatori di oggetti e raccolte e espressioni di query dove si intendeva usare l'oggetto anonimo var, quindi cosa Voglio dire è ... proprio come nell'esempio sopra.
quali sono i tuoi pensieri?
Soluzione
Oltre all'uso ovvio di var
con LINQ, lo uso anche per abbreviare le dichiarazioni di variabili pelose per leggibilità, ad es .:
var d = new Dictionary<string, Dictionary<string, Queue<SomeClass>>>();
In generale, ottengo una sorta di conforto (per mancanza di una parola migliore) dalla digitazione statica che mi rende riluttante a rinunciarvi. Mi piace la sensazione di sapere cosa sto facendo quando dichiaro una variabile. Dichiarare una variabile non è solo dire qualcosa al compilatore, ma dire alla persona che legge qualcosa nel tuo codice.
Lascia che ti faccia un esempio. Supponiamo di avere un metodo che restituisce un List<string>
. Questo codice è certamente corretto, e penso che sia come il 90% degli sviluppatori C # probabilmente lo scriverebbe:
List<string> list = MyMethod();
Ovviamente, vero? In effetti, ecco un posto in cui puoi usare facilmente rows
.
Abbastanza vero. Ma questa versione del codice non sta semplicemente dichiarando una variabile, ma mi sta dicendo cosa intende fare la persona che l'ha scritto:
IEnumerable<string> list = MyMethod();
Lo sviluppatore che ha scritto quel codice mi sta dicendo " Non cambierò questo elenco, né userò un indice per accedere ai suoi membri. Tutto ciò che farò è iterare attraverso di esso. & Quot; Sono molte le informazioni da comunicare in un'unica riga di codice. È qualcosa che ti arrendi se usi IEnumerable<DataRow>
.
Ovviamente, non ti arrendi se non lo stavi usando in primo luogo. Se sei il tipo di sviluppatore che scriverebbe quella riga di codice, sai già che non useresti IEnumerable<T>
lì.
Modifica:
Ho appena riletto il post di Jon Skeet e questa citazione di Eric Lippert è saltata fuori da me:
I locali tipizzati in modo implicito sono solo un piccolo modo in cui puoi de-enfatizzare il come e quindi sottolineare il cosa.
Penso che in realtà in molti casi l'uso della tipizzazione implicita stia lasciando ciò che è implicito. Va bene non soffermarsi sul cosa. Ad esempio, scriverò casualmente una query LINQ come:
var rows = from DataRow r in parentRow.GetChildRows(myRelation)
where r.Field<bool>("Flag")
orderby r.Field<int>("SortKey")
select r;
Quando leggo quel codice, una delle cose che penso quando lo leggo è " <=> è un <=>. " Perché so che le query LINQ restituite sono <=> e posso vedere il tipo di oggetto selezionato proprio lì.
Questo è un caso in cui ciò che non è stato reso esplicito. Mi è rimasto da dedurre.
Ora, in circa il 90% dei casi in cui utilizzo LINQ, questo non ha importanza. Perché il 90% delle volte, la riga di codice successiva è:
foreach (DataRow r in rows)
Ma non è difficile immaginare il codice in cui sarebbe molto utile dichiarare <=> come <=> - codice in cui venivano interrogati molti tipi diversi di oggetti, non era possibile inserire la dichiarazione della query accanto all'iterazione e sarebbe utile poter ispezionare <=> con IntelliSense. Ed è una cosa, non una cosa.
Altri suggerimenti
Otterrai una grande varietà di opinioni su questo - da " usa var ovunque " a " usa solo var con tipi anonimi, dove in pratica devi. " Mi piace Il punto di vista di Eric Lippert :
Tutto il codice è un'astrazione. È cosa il codice è & # 8220; in realtà & # 8221; fare è manipolazione dei dati? No. numeri? Bit? No. Tensioni? No. Elettroni? Si ma comprendere il codice a livello di gli elettroni è una cattiva idea! L'arte di la programmazione è capire quale sia il diritto il livello di astrazione è per pubblico.
In una lingua di alto livello c'è sempre questa tensione tra COSA il codice fa (semanticamente) e COME il il codice lo compie. Manutenzione i programmatori devono capire entrambi il cosa e il come se & # 8217; stanno andando avere successo nel fare cambiamenti.
L'intero punto di LINQ è che de-enfatizza in modo massiccio il " come " e enfatizza in modo massiccio il " what " ;. Di usando una comprensione di query, il il programmatore sta dicendo al futuro pubblico " Credo che dovresti né sapere né preoccuparsi esattamente di come questo il set di risultati è in fase di calcolo, ma tu dovrebbe preoccuparsi molto di ciò che il la semantica dell'insieme risultante è. " Rendono il codice più vicino al processo aziendale in corso di attuazione e più lontano dai bit e dagli elettroni che lo fanno andare.
I locali tipizzati in modo implicito sono solo uno piccolo modo in cui è possibile delimitare il come e quindi enfatizzare il che cosa. Se questa è la cosa giusta fare in un caso particolare è un giudizio. Quindi lo dico alla gente se la conoscenza del tipo è pertinente e la sua scelta è cruciale per il proseguimento del metodo, quindi non utilizzare la digitazione implicita. La digitazione esplicita dice & Quot; te lo sto dicendo come funziona per un motivo, paga attenzione " ;. La digitazione implicita dice & Quot; it & # 8217; non importa un po 'se questo cosa è un elenco o un Cliente [], ciò che conta è che lo sia una raccolta di clienti. "
Personalmente non tendo di usarlo se il tipo non è ragionevolmente ovvio - dove includo le query LINQ come " ragionevolmente ovvio " ;. Non lo farei per Directory.GetFiles
per esempio, dato che non è davvero ovvio che restituisce un string[]
invece di (diciamo) un FileInfo[]
(o qualcos'altro del tutto) - e questo fa una grande differenza per quello che fare più tardi.
Se c'è una chiamata del costruttore sul lato destro dell'operatore di assegnazione, sono molto più probabile che vada con var
: è palesemente ovvio quale sarà il tipo. Ciò è particolarmente utile con tipi generici complessi, ad es. Dictionary<string,List<int>>
.
Personalmente uso var in due posti:
- Con tipi anonimi, ad es. Relativo a LINQ (dove var è richiesto in alcuni casi)
- Quando l'istruzione dichiara e costruisce un tipo specifico nello stesso tipo
es. questo è un esempio del punto 2:
var names = new List<String>();
Modificato : questo in risposta alla domanda di Jon Skeet.
La risposta sopra è stata infatti semplificata. Fondamentalmente, uso var dove il tipo è:
- Inutile sapere (non che molti posti però)
- Impossibile sapere (LINQ, tipi anonimi)
- Altrimenti noto o cancellato dal codice
Nel caso di un metodo factory, dove tutto ciò che devi sapere nel punto in cui scrivi il codice è che l'oggetto che ricevi è un discendente di qualche tipo e che un tipo ha un metodo factory statico, quindi userei var . In questo modo:
var connection = DatabaseConnection.CreateFromConnectionString("...");
L'esempio sopra è un vero esempio dal mio codice. È chiaro, almeno per me e per le persone che usano questo codice, che connessione è un discendente DatabaseConnection, ma il tipo esatto non è necessario né per comprendere il codice né utilizzarlo.
Ho provato il " usa var ovunque " stile ... ed ecco perché non ho continuato a usarlo.
- Leggibilità degradata a volte
- Limita Intellisense dopo =
- Digitando " var " in realtà non era molto più breve della digitazione di " int " ;, " string " ;, ecc., specialmente con intellisense.
Detto questo, lo uso ancora con LINQ.
Proveniente dalla terra della programmazione funzionale, dove l'inferenza del tipo domina il giorno, uso var
per tutti i locali dove possibile.
In Visual Studio, se ti stai mai chiedendo quale sia il tipo di qualsiasi locale, tutto ciò che devi fare è passarci sopra con il mouse.
Questo post ha alcune buone linee guida su quando usare l'interfaccia di tipo var o tipi di oggetto.
Tendo a usare var
ovunque, ma i miei colleghi hanno detto basta, è meno leggibile per noi. Quindi ora uso <=> solo su tipi anonimi, query LINQ e dove si trova il costruttore sul lato destro.
Penso che sia interessante notare come questo di solito viene gestito in Haskell. Grazie al isomorfismo di Curry-Howard , il tipo (più generale) di qualsiasi espressione in Haskell può essere dedotto, e quindi le dichiarazioni di tipo non sono essenzialmente richieste da nessuna parte, con poche eccezioni; ad esempio, a volte vuoi deliberatamente limitare il tipo a qualcosa di più specifico di quanto si supponga.
Naturalmente, ciò che è richiesto e ciò che è raccomandato non sono la stessa cosa; in pratica, la convenzione sembra essere che le definizioni di livello superiore abbiano sempre dichiarazioni di tipo, mentre le definizioni localizzate hanno lasciato le dichiarazioni di tipo. Questo sembra trovare un buon equilibrio tra esplicito per la leggibilità della definizione nel suo insieme, in contrasto con la brevità per la leggibilità del & Quot locale; helper & Quot; oppure " temporaneo " definizioni. Se ho capito bene, non puoi usare var
per & Quot; top-level & Quot; definizioni (come un metodo o una funzione globale) in primo luogo, quindi suppongo che ciò si traduca in " usa int
ovunque puoi " nel mondo C #. Naturalmente, digitando & Quot; <=> & Quot; è lo stesso numero di sequenze di tasti di " <=> " ;, ma la maggior parte degli esempi sarà più lunga di quella.