In teoria, un metodo statico dovrebbe funzionare leggermente meglio di un metodo di istanza, a parità di altre condizioni, a causa del this
parametro nascosto aggiuntivo .
In pratica, questo fa così poca differenza che sarà nascosto nel rumore delle varie decisioni del compilatore. (Quindi due persone potrebbero "dimostrare" uno migliore dell'altro con risultati in disaccordo). Non da ultimo dal momento che this
normalmente viene passato in un registro ed è spesso in quel registro per cominciare.
Quest'ultimo punto significa che in teoria, dovremmo aspettarci un metodo statico che prende un oggetto come parametro e fa qualcosa con esso per essere leggermente meno buono dell'equivalente come istanza su quello stesso oggetto. Di nuovo, però, la differenza è così piccola che se provassi a misurarla probabilmente finiresti per misurare qualche altra decisione del compilatore. (Soprattutto perché anche la probabilità che quel riferimento rimanga in un registro per tutto il tempo è piuttosto alta).
Le reali differenze di prestazioni dipenderanno dal fatto che tu abbia artificialmente in memoria oggetti per fare qualcosa che dovrebbe essere naturalmente statico, o che tu stia aggrovigliando catene di oggetti che passano in modi complicati per fare ciò che dovrebbe essere naturalmente un'istanza.
Quindi per il numero 1. Quando mantenere lo stato non è un problema, è sempre meglio essere statici, perché è a questo che serve . Non è un problema di prestazioni, anche se esiste una regola generale per giocare bene con le ottimizzazioni del compilatore: è più probabile che qualcuno si sia dedicato allo sforzo di ottimizzare i casi che si presentano con un uso normale rispetto a quelli che ne escono con un uso strano.
Numero 2. Non fa differenza. C'è una certa quantità di costo per classe per ogni membro che si riferisce sia alla quantità di metadati che ci sono, alla quantità di codice presente nel file DLL o EXE effettivo, sia alla quantità di codice jitted che ci sarà. È lo stesso sia che si tratti di istanza o di statico.
Con l'elemento 3, this
è come this
fa. Tuttavia nota:
Il this
parametro viene passato in un registro particolare. Quando si chiama un metodo di istanza all'interno della stessa classe, probabilmente sarà già in quel registro (a meno che non sia stato nascosto e il registro utilizzato per qualche motivo) e quindi non è richiesta alcuna azione per impostare this
ciò su cui deve essere impostato . Ciò si applica in una certa misura, ad esempio, ai primi due parametri del metodo che sono i primi due parametri di una chiamata che effettua.
Poiché sarà chiaro che this
non è nullo, in alcuni casi potrebbe essere utilizzato per ottimizzare le chiamate.
Poiché sarà chiaro che this
non è nullo, ciò potrebbe rendere di nuovo più efficienti le chiamate di metodo inline, poiché il codice prodotto per falsificare la chiamata al metodo può omettere alcuni controlli nulli di cui potrebbe comunque aver bisogno.
Detto questo, gli assegni nulli sono economici!
Vale la pena notare che i metodi statici generici che agiscono su un oggetto, piuttosto che i metodi di istanza, possono ridurre alcuni dei costi discussi su http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- gli-associati-overhead / nel caso in cui quel dato statico non è chiamato per un dato tipo. Come dice lui "Per inciso, risulta che i metodi di estensione sono un ottimo modo per rendere le astrazioni generiche più pay-per-play".
Tuttavia, si noti che questo si riferisce solo alla creazione di istanze di altri tipi utilizzati dal metodo, che altrimenti non esistono. In quanto tale, in realtà non si applica a molti casi (qualche altro metodo di istanza ha utilizzato quel tipo, qualche altro codice da qualche altra parte ha utilizzato quel tipo).
Sommario:
- Per lo più i costi delle prestazioni dell'istanza rispetto a quella statica sono inferiori a trascurabili.
- I costi generalmente vengono quando si abusa dell'elettricità statica, ad esempio o viceversa. Se non fai parte della tua decisione tra statico e istanza, è più probabile che tu ottenga il risultato corretto.
- Ci sono rari casi in cui i metodi generici statici in un altro tipo comportano la creazione di un numero inferiore di tipi rispetto ai metodi generici di istanza, che a volte possono far sì che a volte abbia un piccolo vantaggio di essere usati raramente (e "raramente" si riferisce ai tipi con cui è usato nel durata dell'applicazione, non quanto spesso viene chiamata). Una volta capito ciò di cui sta parlando in quell'articolo, vedrai che è comunque irrilevante al 100% per la maggior parte delle decisioni statiche contro istanze. Modifica: e per lo più ha quel costo solo con ngen, non con codice jitted.
Modifica: una nota su quanto siano economici i null-check (che ho affermato sopra). La maggior parte dei controlli null in .NET non verificano affatto la presenza di null, piuttosto continuano ciò che avrebbero fatto supponendo che funzionasse e, se si verifica un'eccezione di accesso, viene trasformata in un file NullReferenceException
. Di conseguenza, soprattutto quando concettualmente il codice C # prevede un controllo null perché accede a un membro dell'istanza, il costo se riesce è effettivamente zero. Un'eccezione sarebbe rappresentata da alcune chiamate inline, (perché vogliono comportarsi come se chiamassero un membro dell'istanza) e premono semplicemente un campo per attivare lo stesso comportamento, quindi sono anche molto economiche e possono comunque essere lasciate fuori comunque (es. se il primo passo nel metodo prevedeva l'accesso a un campo così com'era).