Ich fragte mich, ob mir jemand einen Überblick geben könnte, warum ich sie verwenden würde und welchen Vorteil ich dabei gewinnen würde.
c#
class
architecture
Asterix
quelle
quelle
Antworten:
Teilklassen werden am häufigsten verwendet, um Codegeneratoren / -designern das Leben zu erleichtern. Mit Teilklassen kann der Generator einfach den Code ausgeben, den er ausgeben muss, und er muss sich nicht mit Benutzeränderungen an der Datei befassen. Benutzer können die Klasse ebenfalls mit neuen Mitgliedern versehen, indem sie eine zweite Teilklasse haben. Dies bietet einen sehr sauberen Rahmen für die Trennung von Bedenken.
Eine bessere Sichtweise ist es, zu sehen, wie Designer vor Teilklassen funktionierten. Der WinForms-Designer spuckte den gesamten Code innerhalb einer Region mit stark formulierten Kommentaren aus, dass der Code nicht geändert werden sollte. Es mussten alle Arten von Heuristiken eingefügt werden, um den generierten Code für die spätere Verarbeitung zu finden. Jetzt kann es einfach die Datei designer.cs öffnen und hat ein hohes Maß an Sicherheit, dass sie nur für den Designer relevanten Code enthält.
quelle
Eine andere Verwendung besteht darin, die Implementierung verschiedener Schnittstellen aufzuteilen, z.
quelle
Implements
Schlüsselwort verwendet, um zu kennzeichnen, dass eine Methode zu einer Schnittstelle gehört)Abgesehen von den anderen Antworten ...
Ich fand sie hilfreich als Sprungbrett bei der Umgestaltung von Gottklassen. Wenn eine Klasse mehrere Verantwortlichkeiten hat (insbesondere wenn es sich um eine sehr große Codedatei handelt), finde ich es vorteilhaft, 1x Teilklasse pro Verantwortung als ersten Durchgang für das Organisieren und anschließende Umgestalten des Codes hinzuzufügen.
Dies ist sehr hilfreich, da es dazu beitragen kann, den Code besser lesbar zu machen, ohne das Ausführungsverhalten tatsächlich zu beeinträchtigen. Es kann auch helfen, festzustellen, wann eine Verantwortung leicht umzugestalten ist oder eng mit anderen Aspekten verknüpft ist.
Um klar zu sein, ist dies immer noch ein schlechter Code. Am Ende der Entwicklung möchten Sie immer noch eine Verantwortung pro Klasse ( NICHT pro Teilklasse). Es ist nur ein Sprungbrett :)
quelle
Nur teilweise Methodendeklaration Auch der Code wird nur mit Methodendeklaration kompiliert. Wenn die Implementierung der Methode nicht vorhanden ist, kann der Compiler diesen Code sicher entfernen, und es tritt kein Fehler bei der Kompilierung auf.
So überprüfen Sie Punkt 4. Erstellen Sie einfach ein Winform-Projekt, fügen Sie diese Zeile nach dem Form1-Konstruktor ein und versuchen Sie, den Code zu kompilieren
Bei der Implementierung von Teilklassen sind folgende Punkte zu beachten:
quelle
Eine großartige Verwendung besteht darin, generierten Code von handgeschriebenem Code zu trennen, der zur selben Klasse gehört.
Da LINQ to SQL beispielsweise Teilklassen verwendet, können Sie Ihre eigene Implementierung bestimmter Funktionen (z. B. Viele-zu-Viele-Beziehungen) schreiben, und diese benutzerdefinierten Codeteile werden beim erneuten Generieren des Codes nicht überschrieben.
Gleiches gilt für WinForms-Code. Der gesamte vom Designer generierte Code wird in einer Datei gespeichert, die Sie normalerweise nicht berühren. Ihr handgeschriebener Code wird in einer anderen Datei gespeichert. Auf diese Weise werden Ihre Änderungen nicht weggeblasen, wenn Sie etwas in Designer ändern.
quelle
Es ist richtig, dass Partial Class bei der automatischen Codegenerierung verwendet wird. Eine Verwendung kann darin bestehen, eine große Klassendatei zu verwalten, die möglicherweise tausend Codezeilen enthält. Sie wissen nie, dass Ihre Klasse möglicherweise zehntausend Zeilen enthält, und Sie möchten keine neue Klasse mit einem anderen Namen erstellen.
Eine andere mögliche Verwendung könnte sein, dass mehr als ein Entwickler an derselben Klasse arbeiten kann, da sie an verschiedenen Orten gespeichert sind. Die Leute mögen lachen, aber man weiß nie, dass es manchmal eine Handvoll sein kann.
Product1.cs
Product2.cs
Hoffe es macht Sinn!
quelle
Teilklassen umfassen mehrere Dateien.
Wie können Sie den Teilmodifikator für eine C # -Klassendeklaration verwenden?
Mit Teilklassen können Sie eine Klasse physisch in mehrere Dateien aufteilen. Dies wird häufig von Codegeneratoren durchgeführt.
Beispiel
Mit normalen C # -Klassen können Sie eine Klasse nicht in zwei separaten Dateien im selben Projekt deklarieren. Aber mit dem
partial
Modifikator können Sie.Dies ist nützlich, wenn eine Datei häufig bearbeitet wird und die andere maschinell generiert oder selten bearbeitet wird.
Hier ist ein Beispiel zur Verdeutlichung:
Inhalt der Datei A1.cs: C #
Inhalt der Datei A2.cs: C #
Ausgabe:
Teilweise ist hier erforderlich.
Wenn Sie den
partial
Modifikator entfernen , wird eine Fehlermeldung mit folgendem Text angezeigt:Trinkgeld:
Um dies zu beheben, können Sie entweder das
partial
Schlüsselwort verwenden oder einen der Klassennamen ändern.Wie geht der C # -Compiler mit Teilklassen um?
Wenn Sie das obige Programm zerlegen (mit IL Disassembler), sehen Sie, dass die Dateien A1.cs und A2.cs entfernt werden. Sie werden feststellen, dass die Klasse A vorhanden ist.
Klasse A enthält die Methoden A1 und A2 im selben Codeblock. Die beiden Klassen wurden zu einer zusammengefasst.
Kompiliertes Ergebnis von A1.cs und A2.cs: C #
Zusammenfassung
quelle
Halten Sie alles so sauber wie möglich, wenn Sie mit großen Klassen arbeiten oder wenn Sie in einem Team arbeiten. Sie können es bearbeiten, ohne es zu überschreiben (oder immer Änderungen zu übernehmen).
quelle
Die Hauptverwendung für Teilklassen ist der generierte Code. Wenn Sie sich das WPF-Netzwerk (Windows Presentation Foundation) ansehen, definieren Sie Ihre Benutzeroberfläche mit Markup (XML). Dieses Markup wird in Teilklassen kompiliert. Sie füllen den Code mit eigenen Teilklassen aus.
quelle
Wenn Sie eine ausreichend große Klasse haben, die sich nicht für ein effektives Refactoring eignet, hilft die Aufteilung in mehrere Dateien, die Organisation zu gewährleisten.
Wenn Sie beispielsweise eine Datenbank für eine Site haben, die ein Diskussionsforum und ein Produktsystem enthält, und nicht zwei verschiedene Anbieterklassen erstellen möchten (NICHT das Gleiche wie eine Proxy-Klasse, nur um klar zu sein), können Sie dies Erstellen Sie eine einzelne Teilklasse in verschiedenen Dateien, wie z
MyProvider.cs - Kernlogik
MyProvider.Forum.cs - Methoden, die sich speziell auf das Forum beziehen
MyProvider.Product.cs - Methoden für Produkte
Es ist nur eine andere Möglichkeit, die Dinge organisiert zu halten.
Wie bereits erwähnt, ist dies die einzige Möglichkeit, einer generierten Klasse Methoden hinzuzufügen, ohne das Risiko einzugehen, dass Ihre Ergänzungen bei der nächsten Neuerstellung der Klasse zerstört werden. Dies ist praktisch bei vorlagengeneriertem (T4) Code, ORMs usw.
quelle
Als Alternative zu Pre-Compiler-Direktiven.
Wenn Sie (nämlich
#IF DEBUG
) Pre-Compiler-Direktiven verwenden, erhalten Sie einen knorrig aussehenden Code, der mit Ihrem tatsächlichen Release-Code vermischt ist.Sie können eine separate Teilklasse erstellen, die diesen Code enthält, und entweder die gesamte Teilklasse in eine Direktive einschließen oder diese Codedatei nicht an den Compiler senden (was effektiv auch der Fall ist).
quelle
Dienstreferenzen sind ein weiteres Beispiel, bei dem Teilklassen nützlich sind, um generierten Code von vom Benutzer erstelltem Code zu trennen.
Sie können die Serviceklassen "erweitern", ohne sie beim Aktualisieren der Service-Referenz überschreiben zu lassen.
quelle
Eine andere Verwendung, die ich gesehen habe, ist:
Erweiterung einer großen abstrakten Klasse in Bezug auf Datenzugriffslogik,
Ich habe verschiedene Dateien mit Namen Post.cs, Comment.cs, Pages.cs ...
quelle
Die meisten Leute bemerken, dass dies
partial
nur für eine Klasse mit einer generierten Codedatei oder für Schnittstellen verwendet werden sollte. Ich bin anderer Meinung und hier ist der Grund.Schauen wir uns zum Beispiel die C # System.Math-Klasse an ... das ist die Klasse . Ich würde nicht versuchen, mehr als 70 Methoden in dieselbe einzelne Codedatei zu packen. Es wäre ein Albtraum, dies aufrechtzuerhalten.
Das Platzieren jeder mathematischen Methode in einzelnen Teilklassendateien und aller Codedateien in einem mathematischen Ordner im Projekt wäre eine wesentlich sauberere Organisation.
Das Gleiche könnte / würde für viele andere Klassen gelten, die eine große Menge unterschiedlicher Funktionen haben. Beispielsweise kann eine Klasse zum Verwalten der PrivateProfile-API davon profitieren, wenn sie in einen sauberen Satz von Teilklassendateien in einem einzelnen Projektordner aufgeteilt wird.
Persönlich habe ich auch das, was die meisten Leute als "Hilfs-" oder "Dienstprogramm" -Klassen bezeichnen, in einzelne Teildateien für jede Methode oder Methodenfunktionsgruppe aufgeteilt. In einem Projekt verfügt die String-Helfer-Klasse beispielsweise über fast 50 Methoden. Das wäre eine lange unhandliche Codedatei, selbst wenn Regionen verwendet würden. Die Verwendung einzelner Teilklassendateien für jede Methode ist erheblich einfacher zu verwalten.
Ich würde nur vorsichtig sein, wenn ich Teilklassen verwende und dabei das gesamte Layout der Codedateien während des gesamten Projekts konsistent halte. B. das Platzieren von öffentlichen Klassenaufzählungen und privaten Klassenmitgliedern in einer Common.cs-Datei oder einer Datei mit ähnlichem Namen im Ordner, anstatt sie auf die Dateien zu verteilen, es sei denn, sie sind nur für die Teildatei spezifisch, in der sie enthalten sind.
Beachten Sie, dass Sie beim Aufteilen einer Klasse in separate Dateien auch nicht mehr die Texteditor-Trennleiste verwenden können, mit der Sie zwei verschiedene Abschnitte einer aktuellen Datei gleichzeitig anzeigen können.
quelle
Teilklassen ermöglichen es, einem entsprechend gestalteten Programm Funktionen hinzuzufügen, indem lediglich Quelldateien hinzugefügt werden. Beispielsweise könnte ein Dateiimportprogramm so entworfen werden, dass verschiedene Arten bekannter Dateien hinzugefügt werden können, indem Module hinzugefügt werden, die diese verarbeiten. Beispielsweise könnte der Hauptkonverter für Dateitypen eine kleine Klasse enthalten:
Jedes Modul, das einen oder mehrere Arten von Dateikonvertern registrieren möchte, kann Folgendes enthalten:
Beachten Sie, dass die Hauptdatei-Konverterklasse nicht "verfügbar" ist, sondern nur eine kleine Stub-Klasse verfügbar macht, an die sich Add-In-Module anschließen können. Es besteht ein geringes Risiko für Namenskonflikte, aber wenn die "Register" -Routine jedes Add-In-Moduls nach dem Dateityp benannt wird, mit dem es sich befasst, sollten sie wahrscheinlich kein Problem darstellen. Man könnte eine GUID in den Namen der Registrierungsunterroutine stecken, wenn man sich über solche Dinge Sorgen macht.
Bearbeiten / Nachtrag Um es klar auszudrücken, besteht der Zweck darin, ein Mittel bereitzustellen, mit dem eine Vielzahl von getrennten Klassen ein Hauptprogramm oder eine Hauptklasse über sie informieren kann. Das einzige, was der Hauptdateikonverter mit zzFileConverterRegistrar macht, ist, eine Instanz davon zu erstellen und die registerAll-Methode aufzurufen, die das Register-Ereignis auslöst. Jedes Modul, das dieses Ereignis einbinden möchte, kann als Antwort darauf beliebigen Code ausführen (das ist die ganze Idee), aber es gibt nichts, was ein Modul tun könnte, wenn es die Klasse zzFileConverterRegistrar nicht ordnungsgemäß erweitert, außer eine Methode zu definieren, deren Name mit dem eines anderen übereinstimmt . Es wäre sicherlich möglich, dass eine falsch geschriebene Erweiterung eine andere falsch geschriebene Erweiterung beschädigt, aber die Lösung dafür ist, dass jeder, der nicht möchte, dass seine Erweiterung beschädigt wird, sie einfach richtig schreibt.
Ohne Teilklassen könnte man irgendwo in der Hauptdatei-Konverterklasse ein bisschen Code haben, der so aussah:
Das Hinzufügen eines weiteren Konvertermoduls würde jedoch erfordern, dass Sie in diesen Teil des Konvertercodes gehen und den neuen Konverter zur Liste hinzufügen. Mit Teilmethoden ist das nicht mehr nötig - alle Konverter werden automatisch einbezogen.
quelle
IModule
Schnittstelle implementiert werden?IModule
, die implementiert werden , Sie könnten ein Plugin-Framework wie MEF (nur eines von vielen) usw. usw. verwendenTeilklassen halfen kürzlich bei der Quellcodeverwaltung, bei der mehrere Entwickler zu einer Datei hinzufügten, wobei neue Methoden zu demselben Teil der Datei hinzugefügt wurden (automatisiert von Resharper).
Diese Pushs to Git verursachten Zusammenführungskonflikte. Ich habe keine Möglichkeit gefunden, das Zusammenführungstool anzuweisen, die neuen Methoden als vollständigen Codeblock zu verwenden.
Teilklassen in dieser Hinsicht ermöglichen es Entwicklern, sich an eine Version ihrer Datei zu halten, und wir können sie später von Hand wieder zusammenführen.
Beispiel -
quelle
Von MSDN :
1. Zur Kompilierungszeit werden Attribute von Teiltypdefinitionen zusammengeführt. Betrachten Sie beispielsweise die folgenden Erklärungen:
Sie entsprechen den folgenden Erklärungen:
Folgendes wird aus allen Definitionen des Teiltyps zusammengeführt:
XML-Kommentare
Schnittstellen
generische Parameterattribute
Klassenattribute
Mitglieder
2.Eine andere Sache, verschachtelte Teilklassen können auch partiell sein:
quelle
Hier finden Sie eine Liste einiger Vorteile von Teilklassen.
Sie können UI-Designcode und Geschäftslogikcode trennen, damit er leicht zu lesen und zu verstehen ist. Wenn Sie beispielsweise eine Webanwendung mit Visual Studio entwickeln und ein neues Webformular hinzufügen, gibt es zwei Quelldateien: "aspx.cs" und "aspx.designer.cs". Diese beiden Dateien haben dieselbe Klasse mit dem Teilschlüsselwort. Die Klasse ".aspx.cs" enthält den Geschäftslogikcode, während "aspx.designer.cs" die Definition der Benutzeroberfläche enthält.
Bei der Arbeit mit automatisch generierten Quellen kann der Code der Klasse hinzugefügt werden, ohne dass die Quelldatei neu erstellt werden muss. Sie arbeiten beispielsweise mit LINQ to SQL und erstellen eine DBML-Datei. Wenn Sie jetzt eine Tabelle ziehen und ablegen, wird in designer.cs eine Teilklasse erstellt, und alle Tabellenspalten haben Eigenschaften in der Klasse. Sie benötigen mehr Spalten in dieser Tabelle, um das UI-Raster zu binden, möchten jedoch keine neue Spalte zur Datenbanktabelle hinzufügen, damit Sie eine separate Quelldatei für diese Klasse erstellen können, die eine neue Eigenschaft für diese Spalte hat eine Teilklasse sein. Dies wirkt sich zwar auf die Zuordnung zwischen Datenbanktabelle und DBML-Entität aus, Sie können jedoch problemlos ein zusätzliches Feld abrufen. Dies bedeutet, dass Sie den Code selbst schreiben können, ohne den vom System generierten Code zu beeinträchtigen.
Mehrere Entwickler können gleichzeitig den Code für die Klasse schreiben.
Sie können Ihre Anwendung besser verwalten, indem Sie große Klassen komprimieren. Angenommen, Sie haben eine Klasse mit mehreren Schnittstellen, sodass Sie abhängig von den Schnittstellenimplementierungen mehrere Quelldateien erstellen können. Es ist leicht zu verstehen und eine Schnittstelle zu verwalten, auf der die Quelldatei eine Teilklasse hat.
quelle
Immer wenn ich eine Klasse habe, die eine verschachtelte Klasse von signifikanter Größe / Komplexität enthält, markiere ich die Klasse als
partial
und füge die verschachtelte Klasse in eine separate Datei ein. Ich benenne die Datei, die die verschachtelte Klasse enthält, mit der Regel: [Klassenname]. [Verschachtelter Klassenname] .cs.Im folgenden MSDN-Blog wird die Verwendung von Teilklassen mit verschachtelten Klassen für die Wartbarkeit erläutert: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for- Wartbarkeit.aspx
quelle
Ich weiß, dass diese Frage wirklich alt ist, aber ich möchte nur meine Einstellung zu Teilklassen hinzufügen.
Ein Grund, warum ich persönlich Teilklassen verwende, ist das Erstellen von Bindungen für ein Programm, insbesondere für Zustandsautomaten.
Zum Beispiel ist OpenGL eine Zustandsmaschine, es gibt Haufen Methoden, die alle global geändert werden können. Meiner Erfahrung nach bindet OpenGL jedoch etwas Ähnliches wie OpenGL, wo es so viele Methoden gibt, dass die Klasse leicht 10k LOC überschreiten kann.
Teilklassen werden dies für mich aufschlüsseln und mir helfen, schnell Methoden zu finden.
quelle
Teilklassen werden in erster Linie eingeführt, um Codegeneratoren zu unterstützen, damit wir (Benutzer) nicht bei jeder Neuerstellung alle unsere Arbeiten / Änderungen an den generierten Klassen wie der .designer.cs-Klasse von ASP.NET verlieren, fast alle neuen Tools, die generiert werden Code LINQ, EntityFrameworks und ASP.NET verwenden Teilklassen für generierten Code, sodass wir die Logik dieser generierten Codes unter Verwendung von Teilklassen und -methoden sicher hinzufügen oder ändern können. Seien Sie jedoch sehr vorsichtig, bevor Sie dem generierten Code mithilfe von Teilklassen Inhalte hinzufügen Es ist einfacher, wenn wir den Build brechen, aber am schlimmsten, wenn wir Laufzeitfehler einführen. Weitere Informationen finden Sie unter http://www.4guysfromrolla.com/articles/071509-1.aspx
quelle
Ich stelle zwei Verwendungen fest, die ich in den Antworten nicht explizit finden konnte.
Gruppieren von Klassenelementen
Einige Entwickler verwenden Kommentare, um verschiedene "Teile" ihrer Klasse zu trennen. Ein Team kann beispielsweise die folgende Konvention verwenden:
Mit Teilklassen können wir noch einen Schritt weiter gehen und die Abschnitte in separate Dateien aufteilen. Als Konvention kann ein Team jeder Datei den entsprechenden Abschnitt hinzufügen. Oben hätten wir also so etwas wie: MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs.
Wie andere Antworten anspielten, hängt es wahrscheinlich davon ab, wie groß die Klasse in diesem Fall ist, ob es sich lohnt, die Klasse aufzuteilen oder nicht. Wenn es klein ist, ist es wahrscheinlich einfacher, alles in einer Meisterklasse zu haben. Wenn jedoch einer dieser Abschnitte zu groß wird, kann sein Inhalt in eine separate Teilklasse verschoben werden, um die Meisterklasse sauber zu halten. Eine Konvention in diesem Fall könnte darin bestehen, einen Kommentar zu hinterlassen, indem Sie nach der Abschnittsüberschrift etwas wie "Siehe Teilklasse" sagen, z.
Verwalten des Anwendungsbereichs von Anweisungen / Namespace
Dies ist wahrscheinlich ein seltenes Ereignis, es kann jedoch zu einer Namespace-Kollision zwischen zwei Funktionen aus Bibliotheken kommen, die Sie verwenden möchten. In einer einzelnen Klasse können Sie höchstens eine using-Klausel für eine dieser Klassen verwenden. Für den anderen benötigen Sie einen vollständig qualifizierten Namen oder einen Alias. Bei Teilklassen kann man die beiden Funktionssätze in zwei separate Dateien aufteilen, da jeder Namespace und jede Liste mit Anweisungen unterschiedlich ist.
quelle
using Library1 = The.Namespace.You.Need
oderglobal::Root.Of.Namespace