| 

.NET C# Java Javascript Exception

6
Beim Lesen einer Java-Lektüre bin ich darauf gestossen, dass man Klassen verschachteln kann. Nach einem kurzen Test habe ich festgesellt, dass das auch in .NET funktioniert.

Class MeineKlasse
Class MeineUnterklasse
...
End Class
...
End Class


Allerdings frage ich mich, ob so ein Konstrukt wirklich sinnvoll ist, denn wie werden die inneren Klassen dann eigentlich instanziert, wenn diese datentechnisch mit der äusseren Klasse verbunden sind. Und wann macht ein solcher Konstrukt überhaupt Sinn?
27.04.2012
NETProgrammer 21 1 3
4 Antworten
4
Es gibt auch Anwendungsfälle in denen dies durchaus sinnvoll ist.

Zum Beispiel wenn man eine Klasse als strukturierte Datenspeicherung für Funktionen der Hauptklasse braucht, ist es durchaus zulässig diese als Private Unterklasse zu definieren.

public class MyClass {
private class ApiResult {
//Felder, ggf. einzelne einfache Funktionen
}

private List<ApiResult> apiResult = new List<ApiResult>();
//...
}


Durch das Schlüsselwort "partial" kann ich trotzdem dafür sorgen das die Definition der Unterklasse und der Hauptklasse in 2 verschiedenen Dateien liegen und mich somit auch an diese Style-Vorgabe halten. Wobei ich persönlich das nur bei größeren Unterklassen machen würde. Wenns nur um ne Klasse mit 2-5 Feldern ohne Funktionen geht würde ich es auch nicht in ein extra File legen.

Beispiel - File MyClass.cs:
public partial class MyClass {
//Felder
//Properties
//Funktionen
}


Beispiel - File MyClass.ApiResult.cs:
public partial class MyClass {
private class ApiResult {
//Felder, ggf. einzelne einfache Funktionen
}
}
27.04.2012
Floyd 14,6k 3 9
Floyd 14,6k 3 9
Du meinst sicher "partial" und nicht "shared" ;-)
– Gast 27.04.2012
Sorry, war nicht eingeloggt. Kommentar kam von mir... wieso kann man eigentlich immer noch als Gast hier teilnehmen? Ich dachte, das "Feature" wurde entfernt...
ffordermaier 27.04.2012
Oh ja, hab da VB.Net und C# verwechselt ^^
Floyd 27.04.2012
1
+1, genau für solche Fälle setze ich es auch ein. Ein weiteres Beispiel sind Implementierungen von IEnumerator, die ich ausnahmslos als private nested class implementiere.
ffordermaier 27.04.2012
+1, da bin ich dabei! Für solche Anwendungsfälle setze ich ebenfalls Innere Klassen ein
Karl 27.04.2012
1
+1 vor allem für die Idee, größere innere Klassen dank partial-class-Feature in eigene Dateien zu legen
Matthias Hlawatsch 30.04.2012
1
Es gibt vielleicht Situationen, in denen das gewollt ist, aber ich meine die .NET StyleGuide schreibt vor, daß es pro Datei nur eine Klasse geben sollte und geschachtelte Klassen "BÄH" sind.
27.04.2012
TiMeBaNDiT76 294 2 7
"Meinst" Du es nur, oder hast Du eine Quelle dafür? Was genau meinst Du mit "die .NET StyleGuide"? In den "Framework Design Guidelines" von Cwalina und Abrams werden nested types nicht generell abgelehnt, und die dort enthaltenen Coding Style Conventions machen für nested types eine explizite Ausnahme von der "1 Klasse pro Datei"-Regel.
Matthias Hlawatsch 04.05.2012
Ok ... dann habe ich es falsch in Erinnerung. Ich würde nested types eher ablehnen. Ich hatte wohl auch noch keine sinnvolle Verwendung ... bisher :-) ...
TiMeBaNDiT76 04.05.2012
1
Wenn du mit "datentechnisch verbunden" meinst, dass eine Instanz der inneren Klasse an eine Instanz der äußeren Klasse gekoppelt ist (wie das bei nicht-statischen verschachtelten Klassen in Java der Fall ist), dann stimmt das nicht. Innere Klassen in .net verhalten sich wie statische innere Klassen in Java, können also unabhängig von Instanzen der äußeren Klasse verwendet werden.

Um also deine Frage zu beantworten: Du erstellst eine Instanz der inneren Klasse, indem du "new MeineKlasse.MeineUnterKlasse()" schreibst. Innerhalb von MeineKlasse kannst du auch einfach "new MeineUnterKlasse()" schreiben.

Sinn können innere Klassen dann machen, wenn du eine Klasse haben möchtest, die auf private Eigenschaften einer anderen Klasse zugreifen kann. In der Regel wird aber empfohlen, solch ein Design zu vermeiden.
27.04.2012
sepp2k 116 2
1
Geschachtelte Klassen weisen gegenüber "normalen" Klassen zwei Besonderheiten auf:

1) Ihre Sichtbarkeit läßt sich gezielt auf eine einzelne Klasse, nämlich die umschließende Klasse einschränken.

2) Sie haben Zugriff auf private Felder und Methoden einer anderen, nämlich der umschließenden Klasse.

Eine sinnvolle Anwendung von 1) hat Floyd schon benannt - man kann auf diese Weise die Implementierung einer Klasse intern in weitere Klassen strukturieren, ohne dass von diesem Implementierungsgeheimnis etwas nach außen dringt.

2) ist hilfreich, um die öffentliche Schnittstelle einer Klasse zu strukturieren. Eigentlich könnten ja alle Methoden der inneren Klasse auch direkt in der äußeren stehen. Durch das Zusammenfassen in der inneren Klasse läßt sich aber sehr gut herausarbeiten, dass ein Teil der Methoden nur in einem bestimmten Zustand oder zu einem bestimmten Zweck aufrufbar sein sollen. Anwendungsfälle sind zum Beispiel das Builder-Pattern (siehe "Effective Java 2nd Edition", ein entsprechendes Codebeispiel gibt es hier) oder Fluent APIs.

1) und 2) können auch zusammenspielen. Manchmal ist es hilfreich, wenn eine Klasse ein Interface implementiert, weil eine externe Funktionalität genutzt werden soll, die das verlangt. Gleichzeitig soll davon aber nach außen nichts sichtbar sein - aus prinzipiellen Erwägungen oder einfach, weil die Methoden des Interfaces für den Nutzer der Klasse gar keinen Sinn ergäben. Dann kann man sich in etwa so behelfen:

public class Foo 
{
private class Bar : IBar
{
private readonly Foo foo;
public Bar (Foo foo) { this.foo = foo; }
public void DoBar() { this.foo.DoBar(); }
}

public void DoFoo
{
Service.Execute(new Bar(this)); //Service ruft irgendwann DoBar()
}

private void DoBar() { ... }
}


Foo kann dadurch de facto IBar implementieren, ohne dass Nutzer von Foo davon etwas zu sehen bekommen. In .NET läßt sich ein fast ebenso starker Effekt allerdings auch mit sehr viel weniger Aufwand mittels expliziter Implementierung von IBar erzielen, weshalb der Trick dort kaum gebraucht wird. In Java passiert etwas sehr ähnliches implizit durch den Compiler bei der Verwendung von anonymen Klassen (die es in der Form in .NET nicht gibt (kommt aber evtl. mit 4.5?), die man dort aber auch kaum braucht, weil es Events und anonyme Delegates gibt). Der skizzierte Ansatz könnte zum Beispiel zum Tragen kommen, wenn man merkt, dass man dieselbe anonyme Klasse an mehr als einer Stelle in der äußeren Klasse braucht.

Zuguterletzt: wie sepp2k richtig angemerkt hat, entsprechen die geschachtelten Klassen in .NET den statischen geschachtelten Klassen in Java. Eine sinnvolle Anwendung für nicht-statische geschachtelte Klassen ist mir ehrlich gesagt noch nicht untergekommen.
30.04.2012
Matthias Hlawatsch 13,2k 4 9
+1, wie immer sehr gut erklärt
Floyd 30.04.2012

Stelle deine .net-Frage jetzt!