2011-10-24 18 views
19

Sono abbastanza nuovo di C# quindi portami con me.Classi C# - Perché tanti metodi statici?

Una delle prime cose che ho notato su C# è che molte delle classi sono pesanti metodo statico. Per esempio ...

Perché è:

Array.ForEach(arr, proc) 

invece di:

arr.ForEach(proc) 

e perché è:

Array.Sort(arr) 

invece di:

arr.Sort() 

Sentitevi liberi di indicarmi alcune FAQ in rete. Se una risposta dettagliata è in qualche libro da qualche parte, accetterei anche un puntatore a questo. Sto cercando la risposta definitiva su questo, ma la tua speculazione è la benvenuta.

risposta

8

Supponendo che this answer sia corretto, i metodi di istanza richiedono spazio aggiuntivo in una "tabella dei metodi". Rendere statici i metodi dell'array potrebbe essere stata una delle prime decisioni di risparmio di spazio.

Questo, insieme al fatto di evitare che il puntatore this verifichi che i riferimenti Amitd, potrebbe fornire miglioramenti significativi delle prestazioni per qualcosa di così ubiquitario come gli array.

+0

La domanda/risposta a cui ti sei collegato è ciò che stavo cercando. Grazie! Ho scoperto 'List' pochi minuti fa e quella classe funziona in un modo che mi aspettavo. La risposta arriva nel perché Array e List sono progettati in modo diverso. – dharmatech

+0

Infatti, se uno degli amministratori vuole contrassegnare questo come un duplicato della domanda a cui ti sei collegato, sarebbe OK con me. – dharmatech

11

Perché si tratta di classi di utilità. La costruzione di classe è solo un modo per raggrupparli, considerando che non ci sono funzioni libere in C#.

+0

io non lo chiamerei 'Array' una classe di utilità. È la classe base astratta che deriva da tutti gli array ... che sembra un buon posto per fare questi metodi di istanza. Penso che questa sia una buona domanda. – Daniel

+0

@Daniel Forse Array non è una classe di utilità di per sé, ma i metodi statici che offre sicuramente sembrano metodi di utilità che sono stati raggruppati in esso. – Christian

+0

non sono d'accordo sul fatto che stanno prendendo chiaramente un riferimento al proprio oggetto, quindi dovrebbero essere metodi, probabilmente potrebbero ancora essere modificati come metodi di estensione, ma questo potrebbe avere un costo/beneficio troppo basso –

0

La classe Array non è generica e non può essere resa completamente generica in quanto ciò interromperebbe la compatibilità con le versioni precedenti. C'è una sorta di magia in corso in cui gli array implementano IList<T>, ma è solo per gli array a dimensione singola con un limite inferiore di 0 - array "list-ish".

Sto indovinando che i metodi statici sono l'unico modo per aggiungere metodi generici che funzionano su qualsiasi forma di matrice indipendentemente dal fatto che si qualifichi per la magia del compilatore sopra menzionata.

+1

Sei sempre stato in grado di trattare qualsiasi array type ('string []', 'int []', etc) come istanza di 'Array', quindi non penso che l'argomento _lack of generics_ contenga. – Daniel

+0

@Daniel: Il mio punto è che gli array non hanno * qualsiasi * metodo di istanza in cui la firma presenta il tipo dell'elemento. 'Lista ' e così fa - questo mi fa pensare che la spiegazione delle "funzioni di utilità" non regge. Quindi sembra che gli array siano "speciali" in qualche modo. E poiché la "particolarità" è la mancanza di metodi di istanza con un parametro di tipo del ricevente nei metodi signature - * generic *, la mia conclusione è che gli array, nel caso generale, non sono generici. – millimoose

1

Le motivazioni classiche contro statica:

  1. Difficile da testare
  2. Non thread-safe
  3. aumenta la dimensione del codice nella memoria

1) C# ha diversi strumenti a disposizione che rendono i test metodi statici relativamente facili. Confronto tra gli strumenti di simulazione C#, alcuni dei quali supportano la derisione statica: https://stackoverflow.com/questions/64242/rhino-mocks-typemock-moq-or-nmock-which-one-do-you-use-and-why

2) Esistono modi ben noti e performanti per eseguire la creazione/logica di oggetti statici senza perdere la sicurezza del thread in C#. Ad esempio, implementando il pattern Singleton con una classe statica in C# (puoi passare al quinto metodo se le opzioni inadeguate ti annoiano): http://www.yoda.arachsys.com/csharp/singleton.html

3) Come cita @ K-ballo, ogni metodo contribuisce alla dimensione del codice in memoria in C#, piuttosto che i metodi di istanza che ricevono un trattamento speciale.

Detto questo, i 2 esempi specifici che hai evidenziato sono solo un problema di supporto del codice legacy per la classe di array statico prima che i generici e qualche altro codice di zucchero venissero reintrodotti in giorni C# 1.0, come ha detto @Inerdia. Ho provato a rispondere supponendo che avessi più codice a cui ti riferivi, possibilmente includendo librerie esterne.

+2

Perché dovrei testare i metodi del framework? Stai rispondendo alla domanda o stai solo parlando di definire metodi statici o non nel tuo codice? – manojlds

+1

La domanda ha posto domande sul perché così tante statistiche in C#, non sul perché in particolare nel framework. I 2 esempi sono stati metodi framework molto vecchi e ben testati, ma ho pensato che la domanda riguardasse le librerie C# e il codice in generale. Farò anche notare che ci sono metodi framework più recenti con meno test che vale la pena scrivere il tuo test per quando il tuo codice non funzionerà come previsto - non tutto ciò che rende Microsoft è privo di bug. –

1

Percepita funzionalità.

funzioni "utilità" sono a differenza di gran parte delle OO funzionalità è destinato a bersaglio.

Pensa al caso con le collezioni, I/O, la matematica e quasi tutti di utilità.

Con OO in genere modellare il vostro dominio. Nessuna di queste cose si adatta perfettamente al tuo dominio: non è come se tu stessi scrivendo e dicessi "Oh, dobbiamo ordinare un nuovo hashtable, il nostro è pieno". Spesso le utility non si adattano.

Ci avviciniamo molto, ma non è ancora molto OO passare le collezioni (dove è la tua logica di business? Dove metti i metodi che manipolano la tua collezione e quell'altro piccolo pezzo di dati che stai sempre passando con esso?)

Stessa cosa con i numeri e la matematica. È piuttosto difficile avere Integer.sqrt() e Long.sqrt() e Float.sqrt() - semplicemente non ha senso, né "nuovo Math(). Sqrt()". Ci sono molte aree che non si adattano bene. Se stai cercando un modello matematico, OO potrebbe non essere la soluzione migliore. (Ho creato una classe "Complex" e "Matrix" piuttosto completa in Java e li ho resi abbastanza OO, ma facendoli davvero insegnarmi alcuni dei limiti di OO e Java - ho finito per "Usare" principalmente le classi di Groovy)

Non ho mai visto niente da nessuna parte VICINO a OO per modellare la logica aziendale, essere in grado di dimostrare le connessioni tra codice e gestire la relazione tra dati e codice.

Così abbiamo ripiegare su un modello diverso quando ha più senso per farlo.

5

Anche questa regola da FXCOP

CA1822: Mark members as static

Descrizione regola

I membri che non accedono ai dati di istanza o chiamano metodi di istanza possono essere contrassegnati come static (Shared in Visual Basic) . Dopo aver contrassegnato come statici i metodi , il compilatore invierà i siti di chiamata non virtuali a questi membri, . L'emissione di siti di chiamate non virtuali impedirà un controllo al runtime per ogni chiamata che si assicura che il puntatore dell'oggetto corrente non sia nullo. Questo può ottenere un guadagno di prestazioni misurabile per il codice sensibile alle prestazioni . In alcuni casi, l'impossibilità di accedere all'istanza dell'oggetto corrente rappresenta un problema di correttezza.

Problemi correlati