it-swarm.dev

Warum Teilklassen verwenden?

Nach meinem Verständnis bewirkt das Schlüsselwort partial lediglich, dass eine Klasse auf mehrere Quelldateien aufgeteilt wird. Gibt es einen anderen Grund als die Code-Organisation? Ich habe gesehen, dass es dafür in generierten UI-Klassen verwendet wird.

Es scheint ein schlechter Grund zu sein, ein ganzes Keyword zu erstellen. Wenn eine Klasse groß genug ist, um mehrere Dateien zu benötigen, macht sie wahrscheinlich zu viel. Ich dachte, dass Sie es vielleicht verwenden könnten, um eine Klasse für einen anderen Programmierer teilweise zu definieren, aber es wäre besser, eine abstrakte Klasse zu erstellen.

72
Michael K

Dies ist in jedem Szenario sehr nützlich, in dem ein Teil der Klasse von einem benutzerdefinierten Tool generiert wird, da Sie dem generierten Code benutzerdefinierte Logik hinzufügen können, ohne die generierte Klasse zu erben. Übrigens. Aus dem gleichen Grund gibt es auch Teilmethoden.

Es geht nicht nur um die Benutzeroberfläche, sondern auch um andere Technologien wie Linq-To-Sql oder Entity Framework.

113
Ladislav Mrnka

Wie Sie sagen, wird es häufig verwendet, um generierten Code zu trennen. Es hat oft nichts mit der Größe von Klassen/Dateien zu tun.

Der Vorteil der Trennung von generiertem Code liegt im Stil. Generierter Code kann ziemlich hässlich und unlesbar sein und würde viele Codierungsstandards (und StyleCop-Prüfungen) nicht erfüllen, aber das ist in Ordnung, niemand muss ihn lesen oder direkt warten. Wenn Sie es also in einer anderen Datei "verstecken", können Sie sich darauf konzentrieren, sicherzustellen, dass der Rest der Klasse dem Standard entspricht, die StyleCop-Prüfungen besteht und so weiter.

Ein anderer Bereich, in dem ich es verwendet habe, ist der Bereich, in dem eine Klasse mehrere Schnittstellen implementiert. Es kann sehr schön sein, die Implementierung in separate Dateien zu unterteilen. Dies ist jedoch eher eine Frage der persönlichen Präferenz. Ich habe noch nie gesehen, dass Codierungsstandards erforderlich sind ( oder verhindern) dies.

26
Steve

Einer der Entwickler, bei denen ich arbeite, hat sich vor ein paar Wochen für eine ziemlich gute Verwendung bei der Umgestaltung riesiger Gottklassen entschieden, die außer Kontrolle geraten sind und viele öffentliche Methoden haben: indem sie die logischen Funktionen der einzelnen Teile von getrennt haben Die Klasse in separate Teilklassen Sie können die Klasse physisch in die atomareren Einheiten aufteilen, die die Klassen sein sollten, ohne vorhandene Funktionen zu beschädigen. So können Sie sehen, was gemeinsam ist und was nicht. In dieser ersten Phase können Sie die Partials dann einfacher in ihre eigenen unabhängigen Klassen aufteilen und in der gesamten Codebasis implementieren. Ich dachte, das wäre eine schöne Idee.

Im Allgemeinen denke ich jedoch, dass sie nur verwendet werden sollten, um maschinengenerierte Klassen beim Schreiben von neuem Code zu erweitern.

19
user23157

Ich kann mir einige nützliche Szenarien vorstellen, in denen Teiltöne sinnvoll sind. Die meisten davon verwende ich selbst in meinen Projekten:

  • So trennen Sie Tool/IDE/Designer generierten Code von dem Code, den Sie verwalten. Ein gutes Beispiel ist die Datei Form.Designer.cs, Die den vom Designer generierten Code für Windows Forms-Anwendungen enthält. Viele andere .NET-Formate verfügen auch über einen vom Tool generierten Code, der möglicherweise beim Erstellen Ihres Projekts neu generiert werden kann, sodass alle benutzerdefinierten Änderungen entfernt werden. Die Trennung hilft Ihnen dabei, Ihren Code und Änderungen vor solchen automatisierten Änderungen zu schützen.

  • Wenn Sie mehrere Schnittstellen mit viel Code in der Implementierung implementieren. Ich neige dazu, für jede solche Schnittstelle eine separate Teildatei zu verwenden, die so lautet: {Class}.{Interface}.cs. Es ist für mich leicht zu erkennen, in welcher IDE] welche Schnittstelle der {Class} Implementiert und wie.

  • Wenn die Klasse eine oder mehrere verschachtelte Klassen enthalten muss, insbesondere mit genügend Code, um in eine separate Datei eingefügt zu werden. Ich würde mich an das obige Muster halten und die Namenskonvention {Class}.{NestedClass}.cs Für jede verschachtelte Klasse verwenden. Eine ähnliche Praxis wird bereits von Virtlinks Antwort erwähnt.

  • Wenn ich static Klassen schreibe, die Erweiterungsmethoden enthalten. Es ist häufig der Fall, ähnlichen Klassen oder Schnittstellen dieselbe Logik für Erweiterungsmethoden bereitzustellen - wie beispielsweise Reverse für generische und nicht generische Sammlungen. Ich würde alle Erweiterungsmethoden für eine einzelne Klasse oder Schnittstelle in einen separaten Teil der statischen Klasse einfügen. Zum Beispiel hätte ich alle Erweiterungsmethoden für die IList -Schnittstelle an einer Stelle und die gleichen Methoden wie für IList<T> In einer anderen Datei. Ein anderer Ansatz wäre, dieselbe Methode (alle ihre Überladungen) in denselben Teil mit allen möglichen Klassen für den Parameter this zu setzen - wie wenn alle Implementierungen Reverse in einer Datei enthalten wären. Es hängt davon ab, welche die Trennung in Bezug auf das Codevolumen oder einige interne Konventionen, an die Sie oder Ihre Organisation möglicherweise festhalten, besser rechtfertigen würde.

  • Ich benutze dies nicht, aber ich habe gesehen, dass einige C/C++ - Leute den hier beschriebenen Ansatz mögen: Erstellen Sie einen Teil für die Klasse nur mit Teilmethoden. Dies ähnelt der C/C++ - Methode, Schnittstellen zu definieren und die Methodendeklaration von der Implementierung zu trennen.

  • Trennung durch rein logische Bedenken. Wenn Sie zufällig mit einer großen Klasse arbeiten, die mehr als einen logischen Satz von Operationen in sich kombiniert, können Sie jeden logisch zusammenhängenden Code in einen separaten Teil aufteilen. Normalerweise widerspricht die Existenz solcher Klassen dem Trennung von Bedenken Prinzip, aber es wird häufig ein realer Fall beobachtet, insbesondere bei älteren Codebasen. Mitbenutzer Steve Evers hat sie in seine Antwort auf diese Frage erwähnt und sie mit dem Namen Gottobjekte bezeichnet. Ich persönlich würde den Ansatz von Teilklassen verwenden, um den Code zu teilen, bevor ein Refactoring derart großer Dateien stattfindet, um meine Arbeit zu vereinfachen und das Refactoring transparenter zu gestalten. Dies reduziert auch die Konflikte, die ich möglicherweise verursachen werde, wenn Versionsverwaltungssysteme wie SVN beteiligt sind.

19
Ivaylo Slavov

Ich habe es von niemandem erwähnt gesehen: Ich benutze partial, um verschachtelte Klassen in ihre eigenen Dateien zu setzen.

Alle meine Codedateien enthalten nur eine Klasse, Struktur, Schnittstelle oder Aufzählung. Es macht es viel einfacher, die Definition für ein Objekt zu finden, wenn die Dateinamen den Namen des gesuchten Objekts anzeigen. Und da Visual Studio versucht, die Projektordner mit den Namespaces abzugleichen, sollten die Dateinamen mit den Klassen übereinstimmen.

Dies bedeutet auch, dass eine in NestedClass verschachtelte Klasse MyClass in meinen Projekten eine eigene Datei hat: MyClass.NestedClass.cs.

partial class MyClass
{
    private class NestedClass
    {
        // ...
    }
}

Mit Ausnahme der Verwendung von generiertem Code habe ich nur jemals gesehen, wie sie verwendet wurden, um Gottobjekte zu vertuschen. Der Versuch, eine neue Codebasis zu verstehen oder durch mehrere Quelldateien zu navigieren, die dasselbe Objekt sind, ist soooo ärgerlich.

Also, wenn Sie fragen Why use partial classes? Ich antworte: Wenn Sie keinen generierten Code verwenden, tun Sie dies nicht.

10
Steven Evers

Code-Organisation ist der einzige Grund, aber sie geht tiefer, als es zunächst scheint. Wenn Sie Teilklassen haben, in denen Teile generiert werden, können Sie einfach:

  • Generieren Sie Code neu, ohne manuelle Änderungen in den Klassen erkennen zu müssen, in die Sie schreiben (damit Sie diese Teile nicht überschreiben).
  • Schließen Sie die generierten Teilklassen von Testabdeckung, Quellcodeverwaltung, Metriken usw. aus.
  • Verwenden Sie generierten Code, ohne dass Sie gezwungen sind, Ihre Vererbungsstrategie darauf aufzubauen (Sie können weiterhin von anderen Klassen erben).
6
Deckard

Ich kann mir eine schmutzige Verwendung für sie vorstellen.

Angenommen, Sie haben einige Klassen, die allgemeine Funktionen benötigen, möchten diese Funktionen jedoch nicht in die darüber liegende Vererbungskette einfügen. Oder Sie haben eine Reihe von Klassen, die eine gemeinsame Hilfsklasse verwenden.

Grundsätzlich möchten Sie eine Mehrfachvererbung durchführen, aber C # ist nicht ähnlich. Was Sie also tun, ist partiell zu verwenden, um im Wesentlichen ein #include in C/C++ zu erstellen.

Fügen Sie alle Funktionen in eine Klasse ein oder verwenden Sie die Hilfsklasse. Kopieren Sie dann den Helfer X-mal und benennen Sie ihn in Teilklasse A, B, C um. und setzen Sie teilweise auf Ihre A-, B-, C-Klassen.

Haftungsausschluss: Ja, das ist böse. Tu es niemals - besonders wenn es andere Leute wütend auf dich macht.

1
Mark

Es gibt auch einige Stellen, an denen generierte/implizite Klassen als teilweise deklariert werden. Wenn der Entwickler sie erweitern muss, haben sie vollen Zugriff, ohne sich um das Erben und Überschreiben der gesamten Stelle kümmern zu müssen. Sehen Sie sich die generierten Klassen im temporären Bereich von asp.net an, nachdem Sie zum ersten Mal eine Webforms-Site unter IIS) ausgeführt haben, wenn Sie versuchen möchten, einige Beispiele abzufangen.

1
Bill