Wann ist es angebracht, C # -Teilklassen zu verwenden?

Antworten:

423

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.

JaredPar
quelle
70
Ich bin versucht, dir -1 zu geben, weil du mir Albträume darüber gegeben hast, wie schlimm die Dinge vor dem Teilunterricht waren :)
Jon B
9
@ Jon :), ich denke wir hatten alle diese Albträume.
JaredPar
18
Einmal habe ich einen Codegenerator geschrieben, der mehr als 36K-Zeilen erzeugt (oder wahrscheinlich viel mehr, ich erinnere mich nicht genau), und meine Editoren wurden blockiert, als die Quelle geöffnet wurde. Teilklassen ermöglichten es mir, den produzierten Code ohne 4 GB RAM zu sehen.
Luca
6
Ich würde so weit gehen zu sagen, dass dies die einzige Verwendung für Teilklassen im Produktionscode ist. Obwohl ich akzeptiere, kann es für das Refactoring nützlich sein.
Gordon McAllister
5
@ Gordon - HumerGus Antwort ist eine andere, gegen die ich ziemlich schwer argumentieren kann. Teilklassen können sehr praktisch sein, um Schnittstellen in C # zu implementieren und die Schnittstellenmitglieder klar von den Klassenmitgliedern zu trennen
STW
261

Eine andere Verwendung besteht darin, die Implementierung verschiedener Schnittstellen aufzuteilen, z.

partial class MyClass : IF1, IF2, IF3
{
    // main implementation of MyClass
}


partial class MyClass
{
    // implementation of IF1
}

partial class MyClass
{
    // implementation of IF2
}
Relascope
quelle
6
Guter Punkt! Es ist etwas, das ich zuvor getan und vergessen habe, aber es ist definitiv eine gute Möglichkeit, die Schnittstellenmitglieder klar sichtbar zu halten (insbesondere in C #, da VB.NET das ImplementsSchlüsselwort verwendet, um zu kennzeichnen, dass eine Methode zu einer Schnittstelle gehört)
STW
2
Sehr schöner Punkt, jede Schnittstelle kann von einem Entwickler implementiert werden. Es ist auch eine gute Möglichkeit, die Implementierung der Schnittstelle leicht zu finden.
Kokabi
3
Woher weiß man in der Reihenfolge der Deklaration der Klassen, welche für IF1 oder IF2 ist?
Kuldeep
17
Eine gute Verwendung, aber ein schlechtes Beispiel. Warum oh warum würden Sie alle Schnittstellen in einer
Teilklasse
4
Ha, ich habe gerade diese Frage nachgeschlagen, um zu sehen, ob das Trennen von Schnittstellenimplementierungen eine Standardverwendung für Teilklassen ist. Ich bin froh zu sehen, dass andere es als gute Idee ansehen. Ich stimme @inkredibl darin zu, die Schnittstellendefinition mit der Teilklasse zusammenzusetzen, die sie implementiert.
Kim
171

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 :)

STW
quelle
23
Sehr schön: "... am Ende der Entwicklung wollen Sie noch eine Verantwortung pro Klasse ( NICHT pro
Teilklasse
Für mich ist es kein guter Codierungsstil, kann aber dazu führen, dass schlechte Codes besser aussehen.
Themenfeld
Dem stimme ich voll und ganz zu. Es ist ein guter Schritt, um schlechten Code zu reparieren. Eine Gottklasse ist ein Gottklassenwetter, das über mehrere Dateien verteilt ist oder nicht.
Jimbo
84
  1. Mehrere Entwickler, die Teilklassen verwenden Mehrere Entwickler können problemlos an derselben Klasse arbeiten.
  2. Code Generator Teilklassen werden vor allem von Code - Generator verwendet , um verschiedene Anliegen zu halten trennen
  3. Teilmethoden Mit Teilklassen können Sie auch Teilmethoden definieren, wobei ein Entwickler die Methode einfach definieren und der andere Entwickler sie implementieren kann.
  4. 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

    partial void Ontest(string s);

Bei der Implementierung von Teilklassen sind folgende Punkte zu beachten:

  1. Verwenden Sie in jedem Teil der Teilklasse ein Teilschlüsselwort.
  2. Der Name jedes Teils der Teilklasse sollte gleich sein, aber der Name der Quelldatei für jeden Teil der Teilklasse kann unterschiedlich sein.
  3. Alle Teile einer Teilklasse sollten sich im selben Namespace befinden.
  4. Jeder Teil einer Teilklasse sollte sich in derselben Assembly oder DLL befinden. Mit anderen Worten, Sie können keine Teilklasse in Quelldateien aus einem anderen Klassenbibliotheksprojekt erstellen.
  5. Jeder Teil einer Teilklasse muss dieselbe Zugänglichkeit haben. (dh: privat, öffentlich oder geschützt)
  6. Wenn Sie eine Klasse oder Schnittstelle für eine Teilklasse erben, wird diese von allen Teilen dieser Teilklasse geerbt.
  7. Wenn ein Teil einer Teilklasse versiegelt ist, wird die gesamte Klasse versiegelt.
  8. Wenn ein Teil der Teilklasse abstrakt ist, wird die gesamte Klasse als abstrakte Klasse betrachtet.
hellowahab
quelle
1
Gibt es ein Problem beim Bearbeiten einer Teilklasse, die aus Entity Framework erstellt wurde? Ich möchte einige Klassennamen ändern, die aus einer Tabelle erstellt wurden.
MarceloBarbosa
Ich habe die gleichen Bedenken. Ich möchte wissen, welche Vorteile eine Teilklasse beim Erstellen von Modellen hat, die Entity Framework im Wesentlichen zum Erstellen meiner Datenbank aus einer Code First-Perspektive / -Ansatz / -Implementierung verwendet. Was haben Sie?
Chef_Code
@JimBalter Bitte gehen Sie über diesen Link msdn.microsoft.com/en-us/library/6b0scde8(v=vs.110).aspx . Dies besagt, dass, wenn keine Implementierung vorhanden ist, der Compiler den Code entfernt und kein Kompilierungszeitfehler empfangen wird.
Hellowahab
Wenn Sie eine Klasse oder Schnittstelle für eine Teilklasse erben, wird diese von allen Teilen dieser Teilklasse geerbt.
Die rote Erbse
56

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.

Justin Niessner
quelle
21

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.

public partial class Product
{
    // 50 business logic embedded in methods and properties..
}

public partial class Product
{
    // another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.

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

public partial class Product
{
    //you are writing the business logic for fast moving product
}

Product2.cs

public partial class Product
{
    // Another developer writing some business logic...
}

Hoffe es macht Sinn!

Kausar Ahmed
quelle
13

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 partialModifikator 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:

class Program
{
    static void Main()
    {
        A.A1();
        A.A2();
    }
}

Inhalt der Datei A1.cs: C #

using System;

partial class A
{
    public static void A1()
    {
        Console.WriteLine("A1");
    }
}

Inhalt der Datei A2.cs: C #

using System;

partial class A
{
    public static void A2()
    {
        Console.WriteLine("A2");
    }
}

Ausgabe:

A1
A2

Teilweise ist hier erforderlich.

Wenn Sie den partialModifikator entfernen , wird eine Fehlermeldung mit folgendem Text angezeigt:

[Der Namespace ' <global namespace>' enthält bereits eine Definition für ' A'].

Trinkgeld:

Um dies zu beheben, können Sie entweder das partialSchlü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 #

internal class A
{
    // Methods
    public static void A1()
    {
        Console.WriteLine("A1");
    }

    public static void A2()
    {
        Console.WriteLine("A2");
    }
}

Zusammenfassung

  • Teilklassen können bestimmte C # -Programmiersituationen vereinfachen.
  • Sie werden häufig in Visual Studio beim Erstellen von Windows Forms / WPF-Programmen verwendet.
  • Der maschinengenerierte C # -Code ist separat.
  • Oder die gesamte Beschreibung finden Sie hier .
Vivek Saurav
quelle
2
Schönes Beispiel und gut dokumentiert.
Chef_Code
1
Dies ist die einfachste Erklärung, um imo zu folgen.
Yusha
12

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
11

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.

Cletus
quelle
8

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.

3Dave
quelle
2
Ich würde Partials als Sprungbrett für das Refactoring befürworten (der springende Punkt meiner Antwort), würde sie aber nicht als tatsächliche Lösung für das Schreiben von sauberem Code vorschlagen. Wenn eine Teilklasse sauber von anderen Anliegen der Klasse getrennt ist, warum dann nicht die extra kleinen Anstrengungen unternehmen, um sie zu einer eigenständigen Klasse zu befördern?
STW
@STW: Es kann sein, dass viele Objektinstanzen erstellt und für verschiedene Aufgaben verwendet werden. Um die verschiedenen Aufgaben in verschiedene Klassen zu unterteilen, müsste ermittelt werden, welche Instanzen für welche Aufgaben verwendet wurden - möglicherweise ein viel größeres Unterfangen als das bloße Verschieben von Codeblöcken zwischen Quellmodulen.
Supercat
4
@supercat - Ich verstehe ganz, aber diese Art von Spaghetti sollte aufgeräumt werden. Ich habe viele Narben, wenn ich genau diese Art von Code bereinige, und würde niemals empfehlen, ihn zurückzulassen. Diese Art von Chaos führt garantiert ständig zu Problemen, und die langfristige Auszahlung ist enorm, verglichen mit dem Ignorieren des Problems. Code wie dieser "riecht" nicht, er stinkt wie eine Müllkippe.
STW
1
@supercat - Ich habe versucht, dies mit "Wenn ein Teil sauber von anderen Anliegen getrennt ist ... dann ist es eine kleine Anstrengung" zu qualifizieren. Wenn Sie durch den Schmerz des Entwirrens gehen, sparen Sie normalerweise viel bei der langfristigen Wartung, wenn nicht Rogaine
STW
2
Im Übrigen spiele ich heutzutage mit dem Versuch, Roslyn zu modifizieren, und es wurde unter Verwendung von Teilklassen geschrieben. Viele, viele der Hauptklassen in Roslyn werden als Teilklassen in mehreren Dateien definiert. Und Roslyn wurde von Leuten geschrieben, die ich zumindest für sehr clevere C # -Programmierer halte.
RenniePet
8

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).

STW
quelle
Monogame verwendet diese Strategie.
Zamboni
6

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.

Francesco De Vittori
quelle
6

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 ...

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..
}
Srinivas Reddy Thatiparthy
quelle
6

Die meisten Leute bemerken, dass dies partialnur 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.

deegee
quelle
4

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:

Teilweise öffentliche Klasse zzFileConverterRegistrar
    Ereignisregister (ByVal mainConverter als zzFileConverter)
    Sub registerAll (ByVal mainConverter als zzFileConverter)
        RaiseEvent Register (mainConverter)
    End Sub
Klasse beenden

Jedes Modul, das einen oder mehrere Arten von Dateikonvertern registrieren möchte, kann Folgendes enthalten:

Teilweise öffentliche Klasse zzFileConverterRegistrar
    Private Sub RegisterGif (ByVal mainConverter als zzFileConverter) Behandelt Me.Register
        mainConverter.RegisterConverter ("GIF", GifConverter.NewFactory))
    End Sub
Klasse beenden

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:

  RegisterConverter ("GIF", GifConvertor.NewFactory)
  RegisterConverter ("BMP", BmpConvertor.NewFactory)
  RegisterConverter ("JPEG", JpegConvertor.NewFactory)

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.

Superkatze
quelle
Es funktioniert, aber ein einfaches Plugin-System zum dynamischen Laden dieser Module wäre viel besser und würde dazu beitragen, das Risiko zu vermeiden, dass sich Module gegenseitig beschädigen (es könnte die Module zur Laufzeit laden, anstatt eine Neukompilierung zu erfordern)
STW
Das Risiko, dass sich die Module gegenseitig beschädigen, kann ziemlich gut minimiert werden, wenn sie mit der Klasse zz_ nichts anderes tun, als ein Register-Ereignis zu verknüpfen und eine Routine aufzurufen, um sich selbst zu registrieren. Welche Risiken sehen Sie, die mit einem Plug-In nicht bestehen würden? Plug-Ins sind großartig, wenn vom Endbenutzer erwartet wird, dass er neue Module "einsteckt". Manchmal möchte man jedoch alle Funktionen in einer einzigen Exe zusammenfassen. Es kann praktisch sein, Quelldateien einzubinden, ohne manuell einen Verweis auf die neu hinzugefügten Dateien hinzufügen zu müssen.
Supercat
1
Das Risiko ist in Ihrer Zeile "... wenn sie nichts tun [...] außer ..." ziemlich gut enthalten. Die Sicherheit und Stabilität hängt vollständig vom Entwickler gemäß der Konvention ab und bietet 0% Sicherheit. Wenn Ihr Anwendungsfall darin besteht, sie kompilieren zu lassen (vollkommen gültig, muss nur ein Kompromiss zwischen Gewissen sein), warum sollten dann nicht einfach die Module in separaten Klassen definiert und eine IModuleSchnittstelle implementiert werden?
STW
Es klingt wie ein Fall von "klug" schlecht geworden. Dies sind keine "Module", sondern einzelne Klassen mit vielen Verhaltensweisen und Verantwortlichkeiten, die zur Kompilierungszeit in einer zusammengefasst werden. Es gibt viele bessere Möglichkeiten, dies zu tun - Sie könnten Reflection verwenden, um die kompilierte Assembly nach Klassen zu durchsuchen IModule, die implementiert werden , Sie könnten ein Plugin-Framework wie MEF (nur eines von vielen) usw. usw. verwenden
STW
3

Teilklassen 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 -

  • MainClass.cs - enthält Felder, Konstruktoren usw.
  • MainClass1.cs - ein neuer Code für Entwickler, der gerade implementiert wird
  • MainClass2.cs - ist eine weitere Entwicklerklasse für ihren neuen Code.
Jay
quelle
3

Von MSDN :

1. Zur Kompilierungszeit werden Attribute von Teiltypdefinitionen zusammengeführt. Betrachten Sie beispielsweise die folgenden Erklärungen:

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

Sie entsprechen den folgenden Erklärungen:

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

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:

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}
Eli
quelle
1

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.

Shashi
quelle
1

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

Ɖiamond ǤeezeƦ
quelle
1

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
0

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

Kiran Bheemarti
quelle
0

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:

public class MyClass{  
  //Member variables
  //Constructors
  //Properties
  //Methods
}

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.

//Methods - See partial class

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.

Colm Bhandal
quelle
Es gibt Mechanismen, um eine Namespace-Kollision aufzulösen, z. B. das Umbenennen eines Namespace mit using Library1 = The.Namespace.You.Needoderglobal::Root.Of.Namespace
fjch1997,
Ja, ich nehme an, das ist ein schwacher Anwendungsfall. Aber es ist ein bisschen schöner, Namen nicht vollständig qualifizieren zu müssen. Eher eine nette unbeabsichtigte Nebenwirkung als ein Grund für die Verwendung von Teilklassen.
Colm Bhandal