Ich frage mich, ob mir jemand einen Überblick darüber geben kann, warum ich sie verwenden sollte und welchen Vorteil ich dadurch erhalte.
Antworten
Zu viele Anzeigen?Wenn Sie eine ausreichend große Klasse haben, die sich nicht für ein effektives Refactoring eignet, hilft es, sie in mehrere Dateien aufzuteilen, um die Dinge zu organisieren.
Wenn Sie zum Beispiel eine Datenbank für eine Website haben, die ein Diskussionsforum und ein Produktsystem enthält, und Sie nicht zwei verschiedene Provider-Klassen erstellen wollen (NICHT dasselbe wie eine Proxy-Klasse, nur um das klarzustellen), können Sie eine einzige partielle Klasse in verschiedenen Dateien erstellen, wie
MyProvider.cs - Kernlogik
MyProvider.Forum.cs - Methoden, die sich speziell auf das Forum beziehen
MyProvider.Product.cs - Methoden für Produkte
Das ist nur eine weitere Möglichkeit, Ordnung zu halten.
Wie andere bereits gesagt haben, ist dies auch die einzige Möglichkeit, einer generierten Klasse Methoden hinzuzufügen, ohne Gefahr zu laufen, dass Ihre Ergänzungen bei der nächsten Generierung der Klasse zerstört werden. Dies ist besonders praktisch bei vorlagengeneriertem Code (T4), ORMs usw.
Die meisten Menschen bemerken, dass partial
sollte nur für eine Klasse verwendet werden, die eine generierte Codedatei hat, oder für Schnittstellen. Ich bin anderer Meinung, und hier ist der Grund.
Betrachten wir als Beispiel die C#-Klasse System.Math... das ist Klasse . Ich würde nicht versuchen, 70+ Methoden in eine einzige Codedatei zu packen. Das wäre ein Alptraum in der Wartung.
Wenn man jede mathematische Methode in einzelne Teilklassendateien und alle Codedateien in einen Math-Ordner im Projekt packen würde, wäre die Organisation wesentlich übersichtlicher.
Das Gleiche könnte/würde für viele andere Klassen gelten, die eine große Menge an unterschiedlichen Funktionen haben. Beispielsweise könnte eine Klasse zur Verwaltung der PrivateProfile-API davon profitieren, wenn sie in einen sauberen Satz von Teilklassendateien in einem einzigen Projektordner aufgeteilt würde.
Ich persönlich teile auch das, was die meisten Leute als "Hilfsklassen" oder "Utility-Klassen" bezeichnen, in einzelne Teildateien für jede Methode oder Methodenfunktionsgruppe auf. In einem Projekt hat die Hilfsklasse für Zeichenketten beispielsweise fast 50 Methoden. Das wäre selbst bei Verwendung von Regionen eine lange, unhandliche Codedatei. Es ist wesentlich einfacher, einzelne partielle Klassendateien für jede Methode zu verwenden.
Ich würde nur vorsichtig sein, mit partiellen Klassen und halten alle Code-Datei-Layout konsistent im gesamten Projekt, wenn Sie dies tun. So platzieren Sie alle öffentlichen Enums und privaten Mitglieder der Klasse in einer Common.cs oder ähnlich benannten Datei im Ordner, anstatt sie über die Dateien zu verteilen, es sei denn, sie sind nur für die partielle Datei spezifisch, in der sie enthalten sind.
Beachten Sie, dass Sie bei der Aufteilung einer Klasse in mehrere Dateien auch die Möglichkeit verlieren, die Trennleiste des Texteditors zu verwenden, mit der Sie zwei verschiedene Abschnitte einer aktuellen Datei gleichzeitig anzeigen können.
Eine andere Verwendung, die ich gesehen habe, ist,
Erweiterung einer großen abstrakten Klasse hinsichtlich der Datenzugriffslogik ,
Ich habe verschiedene Dateien mit Namen Post.cs, Comment.cs, Pages.cs...
in Post.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}
in Comment.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}
in Pages.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}
Partielle Klassen ermöglichen es, einem entsprechend gestalteten Programm durch Hinzufügen von Quelldateien weitere Funktionen hinzuzufügen. Zum Beispiel könnte ein Datei-Import-Programm so entworfen werden, dass man verschiedene Arten von bekannten Dateien hinzufügen kann, indem man Module hinzufügt, die sie verarbeiten. Der Hauptdateitypkonverter könnte zum Beispiel eine kleine Klasse enthalten:
Partial Public Class zzFileConverterRegistrar
Event Register(ByVal mainConverter as zzFileConverter)
Sub registerAll(ByVal mainConverter as zzFileConverter)
RaiseEvent Register(mainConverter)
End Sub
End Class
Jedes Modul, das einen oder mehrere Arten von Dateikonvertern registrieren möchte, könnte etwas wie folgt enthalten:
Partial Public Class zzFileConverterRegistrar
Private Sub RegisterGif(ByVal mainConverter as zzFileConverter) Handles Me.Register
mainConverter.RegisterConverter("GIF", GifConverter.NewFactory))
End Sub
End Class
Beachten Sie, dass die Hauptklasse des Dateikonverters nicht "offengelegt" ist, sondern nur eine kleine Stub-Klasse bereitstellt, an die sich Add-In-Module anhängen können. Es besteht ein geringes Risiko von Namenskonflikten, aber wenn die "Registrierungs"-Routine jedes Add-In-Moduls nach dem Dateityp benannt ist, mit dem sie sich befasst, sollten diese wahrscheinlich kein Problem darstellen. Man könnte eine GUID in den Namen der Registrierungsunterroutine einfügen, wenn man sich über solche Dinge Sorgen machen würde.
Bearbeiten/Ergänzung Der Zweck dieser Funktion besteht darin, eine Möglichkeit zu schaffen, mit der verschiedene separate Klassen ein Hauptprogramm oder eine Klasse über sie informieren können. Das einzige, was der Haupt-Dateikonverter mit zzFileConverterRegistrar macht, ist, eine Instanz davon zu erstellen und die registerAll-Methode aufzurufen, die das Ereignis Register auslöst. Jedes Modul, das dieses Ereignis abfangen will, kann als Reaktion darauf beliebigen Code ausführen (das ist die ganze Idee), aber es gibt nichts, was ein Modul durch unsachgemäße Erweiterung der Klasse zzFileConverterRegistrar tun könnte, außer eine Methode zu definieren, deren Name mit dem von etwas anderem übereinstimmt. Es wäre sicherlich möglich, dass eine unsachgemäß geschriebene Erweiterung eine andere unsachgemäß geschriebene Erweiterung kaputt macht, aber die Lösung dafür ist, dass jeder, der nicht will, dass seine Erweiterung kaputt geht, sie einfach richtig schreibt.
Man könnte, ohne partielle Klassen zu verwenden, irgendwo in der Hauptklasse des Dateikonverters ein Stückchen Code haben, das so aussieht:
RegisterConverter("GIF", GifConvertor.NewFactory)
RegisterConverter("BMP", BmpConvertor.NewFactory)
RegisterConverter("JPEG", JpegConvertor.NewFactory)
aber das Hinzufügen eines weiteren Konvertermoduls würde erfordern, dass man in diesen Teil des Konvertercodes geht und den neuen Konverter der Liste hinzufügt. Mit partiellen Methoden ist das nicht mehr nötig - alle Konverter werden automatisch aufgenommen.