Perché utilizzare le classi parziali?

72

A mio avviso, la parola chiave partial non fa altro che consentire a una classe di essere divisa tra diversi file di origine. C'è qualche ragione per farlo se non per l'organizzazione del codice? L'ho visto usato per questo nelle classi UI generate.

Sembra una cattiva ragione per creare un'intera parola chiave. Se una classe è abbastanza grande da richiedere più file, probabilmente sta facendo troppo. Ho pensato che forse potresti usarlo per definire parzialmente una classe per un altro programmatore da qualche parte, ma sarebbe meglio creare una classe astratta.

    
posta Michael K 26.04.2011 - 21:42
fonte

9 risposte

110

È molto utile in ogni scenario in cui una parte della classe viene generata da uno strumento personalizzato perché consente di aggiungere una logica personalizzata al codice generato senza ereditare la classe generata. Btw. ci sono anche metodi parziali per lo stesso motivo.

Non riguarda solo l'interfaccia utente, ma anche altre tecnologie come Linq-To-Sql o Entity Framework lo utilizzano abbastanza pesantemente.

    
risposta data 26.04.2011 - 21:44
fonte
25

Come dici tu, è spesso usato per separare il codice generato. Spesso non ha nulla a che fare con la dimensione delle classi / file.

Il vantaggio di separare il codice generato è uno di stile. Il codice generato può essere piuttosto brutto e illeggibile e fallirebbe molti standard di codifica (e controlli StyleCop), ma va bene, nessuno deve leggerlo o mantenerlo direttamente. Quindi, se lo "nascondi" in un altro file, puoi concentrarti sul fatto che il resto della classe sia conforme allo standard, passa i controlli StyleCop e così via.

Un'altra area in cui l'ho usata è dove una classe implementa più interfacce, può essere molto carino separare l'implementazione in file separati, sebbene questo sia più una questione di preferenze personali, non ho mai visto alcuna codifica gli standard richiedono (o prevengono) questo.

    
risposta data 26.04.2011 - 21:51
fonte
18

Uno degli sviluppatori in cui lavoro mi è stato utile per un paio di settimane fa nel refactoring di enormi classi di Dio che hanno perso il controllo e hanno molti metodi pubblici: separando le funzioni logiche di ogni bit della classe in classi parziali separate è possibile separare fisicamente la classe in unità più atomiche che dovrebbero essere le classi senza rompere alcuna funzionalità esistente, consentendo di vedere ciò che è comune e ciò che non lo è. Con questo come primo stadio è quindi possibile suddividere più facilmente i partial nelle proprie classi indipendenti e implementarli in tutto il codice base. Ho pensato che fosse una buona idea.

Tuttavia, in generale, penso che dovrebbero essere utilizzati solo per aumentare le classi generate dal computer quando si scrive un nuovo codice.

    
risposta data 26.04.2011 - 21:54
fonte
17

Riesco a pensare ad alcuni scenari utili in cui le parziali hanno senso, la maggior parte di loro mi sto utilizzando nei miei progetti:

  • Per separare il codice generato da Tool / IDE / Designer dal codice che stai mantenendo. Un buon esempio è il file Form.Designer.cs che contiene il codice generato dal designer per le applicazioni di Windows Form. Molti altri formati .NET hanno anche un codice generato da uno strumento, che può essere potenzialmente rigenerato quando si crea il progetto e quindi tutte le modifiche personalizzate verranno eliminate. La separazione ti aiuterà a mantenere il tuo codice e le modifiche al sicuro da tali modifiche automatizzate.

  • Quando implementi più interfacce con un sacco di codice nell'implementazione. Tendo ad usare un file parziale separato per ciascuna di queste interfacce, assegnandole un nome come questo: {Class}.{Interface}.cs . È facile per me vedere nell'IDE le interfacce che {Class} sta implementando e come.

  • Quando la classe deve contenere una o più classi nidificate , in particolare con abbastanza codice in esse da inserire in un file separato. Attenersi al modello precedente e utilizzare la convenzione di denominazione {Class}.{NestedClass}.cs per ogni classe nidificata. Prassi simile è già menzionata nella risposta di Virtlink .

  • Quando scrivo static classi che manterranno metodi di estensione . Sarà spesso il caso di fornire la stessa logica del metodo di estensione a classi o interfacce simili, ad esempio Reverse su raccolte generiche e non generiche. Metterei tutti i metodi di estensione per una singola classe o interfaccia in un parziale separato della classe statica. Ad esempio, avrei tutti i metodi di estensione dell'interfaccia IList in un unico posto e gli stessi metodi che sono per IList<T> in un altro file. Un altro approccio sarebbe quello di mettere lo stesso metodo (tutti i suoi overload) nello stesso partial, con tutte le possibili classi per il parametro this - come avere tutte le implementazioni Reverse in un file. Dipende da quale sarebbe meglio giustificare la separazione in termini di volume di codice, o alcune convenzioni interne a cui tu o la tua organizzazione potreste aderire.

  • Non lo uso, ma ho notato che alcuni utenti di C / C ++ apprezzano l'approccio che descriverò qui: crea un partial per la classe solo con i metodi parziali . Questo assomiglia al modo C / C ++ per definire le interfacce e separare la dichiarazione del metodo dall'implementazione.

  • Separazione per puro problemi logici . Se ti capita di lavorare con una classe di grandi dimensioni che combina più di un insieme logico di operazioni in sé, allora puoi separare ogni codice correlato logicamente in un partial separato. Di solito l'esistenza di tali classi è contraria al principio di separazione delle preoccupazioni , ma viene spesso osservato caso reale, in particolare per le codebase precedenti. L'altro utente Steve Evers li ha citati in la sua risposta a questa domanda , riferendosi a loro con il nome God Objects . Personalmente, utilizzerei l'approccio delle classi parziali per suddividere il codice prima che avvenga qualsiasi refactoring di file così grandi, al fine di facilitare il mio lavoro e rendere più trasparente il refactoring. Ciò ridurrà anche i conflitti che causerò potenzialmente quando sono coinvolti sistemi di versioning come SVN.

risposta data 01.04.2014 - 13:28
fonte
14

Non l'ho visto menzionato da nessuno: uso partial per mettere le classi annidate nei propri file.

Tutti i miei file di codice contengono solo una classe, struct, interfaccia o enum. Rende molto più facile trovare la definizione di un oggetto quando i nomi dei file mostrano il nome della cosa che stai cercando. E poiché Visual Studio prova ad abbinare le cartelle del progetto agli spazi dei nomi, i nomi dei file devono corrispondere alle classi.

Questo significa anche che una classe NestedClass nidificata all'interno di MyClass avrà il proprio file nei miei progetti: MyClass.NestedClass.cs .

partial class MyClass
{
    private class NestedClass
    {
        // ...
    }
}
    
risposta data 06.02.2013 - 21:07
fonte
10

Ad eccezione dell'uso del codice generato, ho solo che li ho mai visti usati nel tentativo di coprire oggetti divini . Cercare di capire una nuova base di codice o navigare tra più file sorgente, che sono lo stesso oggetto, è davvero fastidioso.

Quindi quando chiedi Why use partial classes? rispondo: a meno che tu non stia utilizzando il codice generato, non farlo.

    
risposta data 26.04.2011 - 22:42
fonte
6

L'organizzazione del codice è l'unica ragione, ma va più in profondità di quanto non sembri a prima vista. Se hai classi parziali in cui parti sono generate puoi facilmente:

  • Rigenera il codice senza dover rilevare le modifiche manuali nelle classi in cui scrivi (in modo da non sovrascrivere quelle parti).
  • Escludi le classi parziali generate dalla copertura del test, dal controllo del codice sorgente, dalle metriche, ecc.
  • Utilizza il codice generato senza costringerti a basare la tua strategia di ereditarietà attorno ad esso (puoi comunque ereditare da altre classi).
risposta data 26.04.2011 - 21:58
fonte
1

Ci sono anche alcuni posti in cui le classi generate / implicite sono dichiarate parziali quindi se Dev ha bisogno di estenderle hanno pieno accesso senza doversi preoccupare di ereditare e sovrascrivere tutto il luogo. Osserva le classi generate nell'area temp di asp.net dopo aver eseguito un sito Web per la prima volta in IIS se vuoi provare a cogliere alcuni esempi.

    
risposta data 26.04.2011 - 22:43
fonte
1

Posso pensare a un uso sporco per loro.

Supponiamo che tu abbia alcune classi che hanno bisogno di funzionalità comuni, ma non vuoi iniettare quella funzionalità nella catena di ereditarietà sopra di loro. Oppure, hai una serie di classi che usano una classe helper comune.

Fondamentalmente vuoi fare ereditarietà multiple ma C # no likey. Quindi quello che fai è usare parzial- mente per creare ciò che è essenzialmente un #include in C / C ++;

Metti tutte le funzionalità in una classe, o usa la classe helper. Quindi copia l'helper X volte e rinominalo classe parziale A, B, C. e aggiungi parziali alle tue classi A, B, C.

Disclaimer: Sì, questo è malvagio. Non farlo mai, soprattutto se farà arrabbiare gli altri con te.

    
risposta data 13.07.2011 - 09:37
fonte

Leggi altre domande sui tag