Domanda

    

Questa domanda ha già una risposta qui:

         

Ecco cosa MSDN dice sotto Quando usare le classi statiche :

static class CompanyInfo
{
    public static string GetCompanyName() { return "CompanyName"; }
    public static string GetCompanyAddress() { return "CompanyAddress"; }
    //...
}
     

Usa una classe statica come unità di   organizzazione per i metodi no   associato a oggetti particolari.   Inoltre, una classe statica può creare il tuo   implementazione più semplice e veloce   perché non devi creare un   oggetto per chiamare i suoi metodi.   È utile organizzare i metodi   all'interno della classe in modo significativo,   come i metodi della classe di matematica   nello spazio dei nomi di sistema.

Per me, questo esempio non sembra coprire molti possibili scenari di utilizzo per le classi statiche. In passato ho usato classi statiche per suite stateless di funzioni correlate, ma questo è tutto. Quindi, in quali circostanze (e non dovrebbe) una classe dovrebbe essere dichiarata statica?

È stato utile?

Soluzione

Ho scritto i miei pensieri sulle classi statiche in una precedente risposta Stack Overflow: Classe con metodo singolo - approccio migliore?

Adoravo le classi di utilità riempite con metodi statici. Fecero un grande consolidamento dei metodi di aiuto che altrimenti sarebbero dovuti causare ridondanza e inferno di manutenzione. Sono molto facili da usare, nessuna istanza, nessuno smaltimento, solo il fuoco e lo scordo. Immagino che questo sia stato il mio primo inconsapevole tentativo di creare un'architettura orientata ai servizi - molti servizi senza stato che hanno fatto il loro lavoro e nient'altro. Man mano che cresce un sistema, tuttavia, arrivano i draghi.

Il polimorfismo

Supponiamo di avere il metodo UtilityClass.SomeMethod che ronza felicemente. All'improvviso dobbiamo modificare leggermente la funzionalità. La maggior parte delle funzionalità è la stessa, ma dobbiamo comunque cambiare un paio di parti. Se non fosse stato un metodo statico, avremmo potuto creare una classe derivata e modificare i contenuti del metodo secondo necessità. Essendo un metodo statico, non possiamo. Certo, se abbiamo solo bisogno di aggiungere funzionalità prima o dopo il vecchio metodo, possiamo creare una nuova classe e chiamare quella vecchia al suo interno - ma questo è solo grossolano.

Problemi di interfaccia

I metodi statici non possono essere definiti tramite interfacce per motivi logici. E poiché non possiamo ignorare i metodi statici, le classi statiche sono inutili quando dobbiamo passarle in giro dalla loro interfaccia. Questo ci rende incapaci di usare le classi statiche come parte di un modello di strategia. Potremmo correggere alcuni problemi con delegati di passaggio anziché interfacce .

Test

Questo in pratica va di pari passo con i problemi dell'interfaccia menzionati sopra. Poiché la nostra capacità di scambiare le implementazioni è molto limitata, avremo anche problemi a sostituire il codice di produzione con il codice di prova. Ancora una volta, possiamo riassumerli, ma ci richiederà di modificare gran parte del nostro codice solo per poter accettare wrapper invece degli oggetti reali.

Foster blob

Poiché i metodi statici vengono generalmente utilizzati come metodi di utilità e i metodi di utilità di solito hanno scopi diversi, finiremo rapidamente con una grande classe riempita con funzionalità non coerente - idealmente, ogni classe dovrebbe avere un unico scopo all'interno del sistema. Preferirei avere un numero di lezioni cinque volte maggiore se i loro scopi sono ben definiti.

Strisciamento dei parametri

Per cominciare, quel piccolo metodo statico carino e innocente potrebbe prendere un singolo parametro. Man mano che la funzionalità aumenta, vengono aggiunti un paio di nuovi parametri. Presto verranno aggiunti ulteriori parametri che sono facoltativi, quindi creiamo sovraccarichi del metodo (o semplicemente aggiungiamo valori predefiniti, nelle lingue che li supportano). In poco tempo, abbiamo un metodo che accetta 10 parametri. Sono richiesti solo i primi tre, i parametri 4-7 sono opzionali. Ma se viene specificato il parametro 6, è necessario compilare anche 7-9 ... Se avessimo creato una classe con il solo scopo di fare ciò che ha fatto questo metodo statico, potremmo risolverlo prendendo i parametri richiesti nel costruttore e consentire all'utente di impostare valori opzionali tramite proprietà o metodi per impostare più valori interdipendenti contemporaneamente. Inoltre, se un metodo è cresciuto fino a questo livello di complessità, molto probabilmente deve essere nella sua stessa classe.

Consumatori esigenti di creare un'istanza di classi senza motivo

Uno degli argomenti più comuni è: perché esigere che i consumatori della nostra classe creino un'istanza per invocare questo singolo metodo, senza averne successivamente bisogno? La creazione di un'istanza di una classe è un'operazione molto economica nella maggior parte delle lingue, quindi la velocità non è un problema. L'aggiunta di una riga aggiuntiva di codice al consumatore è un costo basso per porre le basi di una soluzione molto più sostenibile in futuro. Infine, se si desidera evitare la creazione di istanze, è sufficiente creare un wrapper singleton della propria classe che consenta un facile riutilizzo, sebbene ciò richieda che la classe sia apolide. Se non è stateless, è comunque possibile creare metodi wrapper statici che gestiscono tutto, offrendo comunque tutti i vantaggi a lungo termine. Infine, puoi anche creare una classe che nasconda l'istanza come se fosse un singleton: MyWrapper.Instance è una proprietà che restituisce solo new MyClass ();

Solo un Sith si occupa di assoluti

Naturalmente, ci sono eccezioni alla mia antipatia per i metodi statici. Le vere classi di utilità che non comportano alcun rischio di gonfiamento sono ottimi casi per metodi statici, come System.Convert. Se il tuo progetto è unico e non richiede requisiti per la manutenzione futura, l'architettura complessiva non è davvero molto importante - statica o non statica, non importa - la velocità di sviluppo, comunque.

Standard, standard, standard!

L'uso dei metodi di istanza non ti impedisce di usare anche metodi statici e viceversa. Finché c'è un ragionamento dietro la differenziazione ed è standardizzata. Non c'è niente di peggio che guardare un livello aziendale tentacolare con diversi metodi di implementazione.

Altri suggerimenti

Quando decidi se rendere una classe statica o non statica devi guardare quali informazioni stai cercando di rappresentare. Ciò comporta uno stile di programmazione più " bottom-up " in cui ti concentri sui dati che rappresenti per primi. La classe che stai scrivendo è un oggetto del mondo reale come una roccia o una sedia? Queste cose sono fisiche e hanno attributi fisici come colore, peso che ti dice che potresti voler istanziare più oggetti con proprietà diverse. Potrei desiderare una sedia nera E una sedia rossa allo stesso tempo. Se hai mai bisogno di due configurazioni contemporaneamente, sai immediatamente che dovrai istanziarlo come oggetto in modo che ogni oggetto possa essere unico ed esistere allo stesso tempo.

Dall'altra parte, le funzioni statiche tendono a prestare di più ad azioni che non appartengono a un oggetto del mondo reale o ad un oggetto che puoi facilmente rappresentare. Ricorda che i predecessori di C # sono C ++ e C in cui puoi semplicemente definire funzioni globali che non esistono in una classe. Ciò si presta maggiormente alla programmazione " dall'alto verso il basso . I metodi statici possono essere utilizzati per questi casi in cui non ha senso che un 'oggetto' esegua l'attività. Obbligandoti a utilizzare le classi, ciò semplifica il raggruppamento delle funzionalità correlate che ti aiutano a creare codice più gestibile.

La maggior parte delle classi può essere rappresentata da statica o non statica, ma quando sei in dubbio torna alle tue radici OOP e prova a pensare a ciò che stai rappresentando. È questo un oggetto che sta eseguendo un'azione (un'auto che può accelerare, rallentare, girare) o qualcosa di più astratto (come visualizzare l'output).

Entra in contatto con il tuo OOP interiore e non puoi mai sbagliare!

Per C # 3.0, i metodi di estensione possono esistere solo nelle classi statiche di livello superiore.

Se utilizzi strumenti di analisi del codice (ad es. FxCop ), ti consigliamo di contrassegnare un metodo statico se tale metodo non accede ai dati dell'istanza. La logica è che c'è un aumento delle prestazioni. MSDN: CA1822 - Contrassegna i membri come statici .

È più una linea guida che una regola, davvero ...

Tendo a usare classi statiche per le fabbriche. Ad esempio, questa è la classe di registrazione in uno dei miei progetti:

public static class Log
{
   private static readonly ILoggerFactory _loggerFactory =
      IoC.Resolve<ILoggerFactory>();

   public static ILogger For<T>(T instance)
   {
      return For(typeof(T));
   }

   public static ILogger For(Type type)
   {
      return _loggerFactory.GetLoggerFor(type);
   }
}

Potresti anche aver notato che l'IoC viene chiamato con un dispositivo di accesso statico. La maggior parte delle volte per me, se puoi chiamare metodi statici su una classe, è tutto ciò che puoi fare, quindi contrassegnare la classe come statica per maggiore chiarezza.

Le classi statiche sono molto utili e hanno un posto, ad esempio librerie.

Il miglior esempio che posso fornire è la classe .Net Math, una classe statica dello spazio dei nomi di sistema che contiene una libreria di funzioni matematiche.

È come qualsiasi altra cosa, usa lo strumento giusto per il lavoro e, in caso contrario, puoi abusare di qualsiasi cosa.

Eliminando in bianco le classi statiche come errate, non usarle o dicendo "ci può essere solo una" o nessuno, è sbagliato come sopra usando loro.

C # .Net contiene un numero di classi statiche che viene utilizzato proprio come la classe Math.

Quindi, data la corretta implementazione, sono estremamente utili.

Abbiamo una classe TimeZone statica che contiene una serie di funzioni relative al fuso orario correlate al business, non è necessario creare più istanze della classe così come la classe Math che contiene un insieme di funzioni (metodi) realizzate in TimeZone globalmente accessibili in una classe statica.

Ho iniziato a utilizzare le classi statiche quando desidero utilizzare le funzioni, piuttosto che le classi, come unità di riutilizzo. In precedenza, mi occupavo del male delle classi statiche. Tuttavia, l'apprendimento di F # mi ha fatto vedere loro sotto una nuova luce.

Cosa intendo con questo? Bene, diciamo quando sto elaborando un super DRY , finisco con un mucchio di uno classi di metodi. Potrei semplicemente tirare questi metodi in una classe statica e poi iniettarli in dipendenze usando un delegato. Questo funziona bene anche con il mio contenitore di dipendenza (DI) di scelta Autofac.

Ovviamente prendere una dipendenza diretta da un metodo statico è ancora di solito cattivo (ci sono alcuni usi non malvagi).

Uso le classi statiche come mezzo per definire " funzionalità extra " che un oggetto di un determinato tipo potrebbe usare in un contesto specifico. Di solito si rivelano classi di utilità.

A parte questo, penso che " Usa una classe statica come unità organizzativa per metodi non associati a oggetti particolari. " descrivere abbastanza bene l'uso previsto.

Questa è un'altra domanda vecchia ma molto accesa da quando OOP è entrato. Ci sono molti motivi per usare (o meno) una classe statica, ovviamente e la maggior parte di essi è stata coperta nella moltitudine di risposte.

Aggiungerò solo i miei 2 centesimi a questo, dicendo che, faccio una classe statica, quando questa classe è qualcosa che sarebbe unica nel sistema e che non avrebbe davvero senso avere qualche istanza nel programma . Tuttavia, riservo questo utilizzo per le grandi classi. Non dichiaro mai classi così piccole come nell'esempio MSDN come " statico " e, certamente, non le classi che saranno membri di altre classi.

Mi piace anche notare che i metodi e le classi statici sono due cose diverse da considerare. I principali svantaggi menzionati nella risposta accettata sono i metodi statici. le classi statiche offrono la stessa flessibilità delle classi normali (per quanto riguarda proprietà e parametri) e tutti i metodi utilizzati in esse dovrebbero essere pertinenti allo scopo dell'esistenza della classe.

Un buon esempio, secondo me, di un candidato per una classe statica è un "FileProcessing" classe, che conterrebbe tutti i metodi e le proprietà rilevanti per i vari oggetti del programma per eseguire complesse operazioni FileProcessing. Difficilmente ha significato avere più di un'istanza di questa classe ed essendo statica la renderà prontamente disponibile a tutto nel tuo programma.

Uso solo le classi statiche per i metodi helper, ma con l'avvento di C # 3.0, preferirei usare metodi di estensione per quelli.

Uso raramente metodi di classi statiche per gli stessi motivi per cui utilizzo raramente il singleton "design pattern".

Basato su MSDN :

  1. Non è possibile creare l'istanza per le classi statiche
  2. Se la classe dichiarata come statica, la variabile membro dovrebbe essere statica per quella classe
  3. Sigillato [non può essere ereditato]
  4. Impossibile contenere il costruttore dell'istanza
  5. Gestione della memoria

Esempio: i calcoli matematici (valori matematici) non cambiano [CALCOLO STANDARD PER VALORI DEFINITI]

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top