2010-07-06 10 views
16

A volte uso le parentesi graffe per isolare un blocco di codice per evitare di utilizzare per errore una variabile in un secondo momento. Ad esempio, quando metto più SqlCommand nello stesso metodo, faccio spesso copia-incolla dei blocchi di codice, terminando mescolando i nomi ed eseguendo il doppio di alcuni comandi. L'aggiunta di parentesi graffe aiuta a evitare questa situazione, poiché l'utilizzo di un valore errato di SqlCommand in un posto sbagliato causerà un errore. Ecco una illustrazione:È sbagliato utilizzare le parentesi per scopi di ambito variabile?

Collection<string> existingCategories = new Collection<string>(); 

// Here a beginning of a block 
{ 
    SqlCommand getCategories = new SqlCommand("select Title from Movie.Category where SourceId = @sourceId", sqlConnection, sqlTransaction); 
    getCategories.Parameters.AddWithValue("@sourceId", sourceId); 
    using (SqlDataReader categoriesReader = getCategories.ExecuteReader(System.Data.CommandBehavior.SingleResult)) 
    { 
     while (categoriesReader.Read()) 
     { 
      existingCategories.Add(categoriesReader["Title"].ToString()); 
     } 
    } 
} 

if (!existingCategories.Contains(newCategory)) 
{ 
    SqlCommand addCategory = new SqlCommand("insert into Movie.Category (SourceId, Title) values (@sourceId, @title)", sqlConnection, sqlTransaction); 

    // Now try to make a mistake and write/copy-paste getCategories instead of addCategory. It will not compile. 
    addCategory.Parameters.AddWithValue("@sourceId", sourceId); 
    addCategory.Parameters.AddWithValue("@title", newCategory); 
    addCategory.ExecuteNonQuery(); 
} 

Ora, StyleCop visualizza un avviso ogni volta che un blocco segue una linea vuota. D'altra parte, non mettere una riga vuota renderebbe il codice molto più difficile da capire.

// Something like: 
Collection<string> existingCategories = new Collection<string>(); 
{ 
    // Code here 
} 

// can be understood as (is it easy to notice that semicolon is missing?): 
Collection<string> existingCategories = new Collection<string>() 
{ 
    // Code here 
} 

Quindi,

  1. C'è qualcosa che non va a usare le parentesi per creare blocchi di codice solo per scopi di scope delle variabili?

  2. Se è tutto a posto, come renderlo più leggibile senza violare le regole di StyleCop?

+3

Questi sono chiamati blocchi anonimi. Relativo: http://stackoverflow.com/questions/85282/what-is-the-value-of-an-anonymous-unattached-block-in-c e http://stackoverflow.com/questions/500006/what- is-the-purpose-of-anonymous-blocks-in-c-style-languages ​​ –

risposta

5

Non penso che ci sia qualcosa di sbagliato nell'usare le parentesi puramente per delimitare l'ambito: a volte può essere molto utile.

Caso in questione: mi sono imbattuto in una libreria di profili una volta che utilizzava gli elementi Profile per le sezioni temporali del codice. Questi hanno funzionato misurando il tempo dalla loro creazione alla distruzione, e quindi hanno funzionato al meglio essendo creati in pila e poi distrutti quando sono andati fuori dal campo di applicazione, misurando quindi il tempo trascorso in quel particolare ambito. Se si voleva tempo qualcosa che non aveva intrinsecamente il proprio ambito, quindi aggiungere ulteriori parentesi per definire che l'ambito era probabilmente il modo migliore per andare.

Per quanto riguarda la leggibilità, posso capire perché StyleCop non piace, ma chiunque con qualsiasi esperienza in C/C++/Java/C#/... sa che un paio doppietta definisce un campo di applicazione, e dovrebbe essere abbastanza evidente che è quello che stai cercando di fare.

12

Utilizzare l'istruzione using anziché i blocchi di bretelle nude.

Ciò eviterà gli avvisi e inoltre renderà il codice più efficiente in termini di risorse.

Da una prospettiva più ampia, è consigliabile prendere in considerazione la suddivisione di questo metodo in metodi più piccoli. Usando uno SqlCommand seguito da un altro di solito è meglio fare chiamando un metodo seguito da un altro. Ogni metodo utilizzerà quindi il proprio locale SqlCommand.

+8

Credo che using() richieda un IDisposable, che potrebbe non avere in questo contesto. –

+0

Questo si applica a questo particolare scenario (poiché 'SqlCommand' implementa' IDisposable', ma non risolverebbe il suo caso generale –

+0

È brutto, ma non potresti usare 'do {...} while (false);' invece "Disattivare l'avvertimento sarebbe probabilmente una soluzione migliore, però: –

18

Non c'è niente di sbagliato di per sé con codice di blocco, ma è necessario considerare perché lo stai facendo.

Se si copia e incolla il codice, è probabile che ci si trovi in ​​una situazione in cui si dovrebbe eseguire il refactoring del codice e produrre funzioni che si richiamano ripetutamente anziché eseguire ripetutamente blocchi di codice simili ma diversi.

+4

Sono d'accordo, non c'è nulla di tecnicamente sbagliato, è un reclamo stilistico e potenzialmente un segnale di avvertimento di funzioni lunghe che dovrebbero essere suddivise in parti più piccole e più gestibili. –

+0

"è probabile che ti trovi in ​​una situazione in cui dovresti refactoring il codice": non si tratta di copia/incolla di grandi blocchi di codice. Lo stesso problema si presenterà quando si usa Intellisense se due variabili hanno nomi simili ('sqlGetProductFromTable' vs.' sqlAddProductToTable'). È facile digitare il nome della variabile in modo errato, e poiché per il compilatore, il codice è perfettamente corretto, verrà eseguito, ma produrrà qualcosa di inaspettato. –

+0

@MainMa: Riutilizzare i blocchi non è l'unica ragione per il refactoring. Un metodo che è semplicemente enorme può essere una buona ragione per scomporlo in pezzi più piccoli. –

4

Penso che blocchi del genere siano una buona idea, li uso spesso. È utile quando è necessario separare blocchi di codice troppo piccoli per essere estratti nel metodo o quando il metodo consiste di pochi blocchi di codice simili a a vicenda, ma non con la stessa logica. Permette di dare alle variabili gli stessi nomi senza conflitti di denominazione, e questo rende il corpo del metodo più leggibile.

A proposito, la mia opinione su StyleCop ha una serie di regole predefinite con più regole che l'opportunità è discutibile.

3

Devo dire se dovessi lavorare su questo codice dopo di voi, sarei un po 'offeso dal vostro uso dell'oscilloscopio. Non è, afaik, pratica comune.

Considererei un odore quello che faresti. Penserei che la migliore pratica sarebbe quella di interrompere ogni ambito nel proprio metodo con nomi e documentazione completamente descrittivi.

0

Se è necessario utilizzare le parentesi per limitare l'ambito delle variabili, i metodi sono probabilmente già troppo lunghi. Volevo solo sottolineare ciò che gli altri hanno già scritto.

Problemi correlati