Laden...

Definition von Delegaten, was ist den nun richtig? (innerhalb der Klasse oder des Namespaces)

Erstellt von Vertax vor 12 Jahren Letzter Beitrag vor 12 Jahren 3.781 Views
V
Vertax Themenstarter:in
9 Beiträge seit 2011
vor 12 Jahren
Definition von Delegaten, was ist den nun richtig? (innerhalb der Klasse oder des Namespaces)

Hallo Community,
es ist mal wieder so weit und ich bilde mich momentan weiter.
Habe dazu mal den Guide to C# von Golon Roden gelesen.

Darin meint er:

Obwohl Delegaten so wohl außerhalb wie auch innerhalb einer Klasse definiert werden können, ist es üblich, sie außerhalb einer Klasse zu definieren, da sie ansonsten nur innerhalb der sie umgebenden Klasse verwendbar sind.

Während Bernhard Volz in Einstieg in Visual C# 2008 meint, das Delegaten lieber nicht im Namespace definiert werden sollten, da dadurch nicht ersichtlich ist zu welcher Klasse er gehöre. Der Delegate sollte also lieber mit dem Klassennamen angesprochen werden.

Was ist nun richtig?
Danke im Vorraus.

Hinweis von herbivore vor 12 Jahren

... da sie ansonsten nur innerhalb der sie umgebenden Klasse verwendbar sind.

Dieser Teil der Aussage stimmt so nicht. Ein geschachtelter Delegatentyp ist nur dann nur innerhalb der ihn umgebenden Klasse verwendbar, wenn er private deklariert ist. Wenn man ihn z.B. public definiert ist er überall dort verwendbar, wo auch die Klasse verwendbar ist. Die Verwendbarkeit hängt also weniger an der Schachtelung als vielmehr am Zugriffsmodifier.

5.742 Beiträge seit 2007
vor 12 Jahren

da dadurch nicht ersichtlich ist zu welcher Klasse er gehöre.

Zusammengehörigkeit sollte IMHO bereits der Namespace vermitteln.

Und wirklich "untrennbar" ist ja ein Delegat nie wirklich mit einer Klasse verbunden - im Gegenteil: Delegaten wie Action, Predicate, Func etc. sind ja sehr universell.

Von daher würde ich eher Golo zustimmen.

V
Vertax Themenstarter:in
9 Beiträge seit 2011
vor 12 Jahren

Danke schön, ich hatte auch das Gefühl das Herr Roden mehr Ahnung auf dem Gebiet besitzt. Aber der Weisheits letzter Schluss hat ja keiner für sich gepachtet.

Deshalb wollte ich das ganze lieber nochmal bestätigt bekommen.

5.742 Beiträge seit 2007
vor 12 Jahren

Deshalb wollte ich das ganze lieber nochmal bestätigt bekommen.

Wirklich "bestätigen" kann dir in Sachen Codingstyle niemand etwas - da existieren so viele verschiedene Meinungen wie Entwickler.
Der "Weisheit letzen Schluss", können wir dir daher selbstverständlich auch nicht liefern.

Man kann lediglich Vor- und Nachteile (bzw. Argumente für und gegen) verschiedene Ansätze aufzählen.
"Richtig" oder "Falsch" macht das jedoch keine Variante; letztlich hängt alles - wie so oft - vom Kontext ab 😉

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Vertax,

die Frage ist im Grunde vollkommen unabhängig davon, dass es um Delegaten geht. Es gelten die normalen "Regeln" für geschachtelte Typen (Nested Types). Wenn du dir die anschaust, wirst du gleich mehrere Kriterien finden, die dafür sprechen, Delegaten nicht als geschachtelten Typ zu deklarieren.

herbivore

107 Beiträge seit 2011
vor 12 Jahren

Interessant.

Wenn ich mir das erste Kriterium anschaue:

Verwenden Sie geschachtelte Typen, wenn sich aufgrund der Beziehung zwischen dem geschachtelten Typ und seinem äußeren Typ eine Semantik für den Memberzugriff empfiehlt.

und dann überlege, dass ich im Rahmen des Threadings z.B. Delegaten zum Aktualisieren eines Progressbars verwende, würde ich meinen, dass schon eine Beziehung zwischen der UI-Klasse und dem entsprechenden Delegaten besteht.

Wie seht ihr das?

q.e.d.

5.742 Beiträge seit 2007
vor 12 Jahren

und dann überlege, dass ich im Rahmen des Threadings z.B. Delegaten zum Aktualisieren eines Progressbars verwende

Ich nehme für so etwas generell Action und bediene mich für Parameterübergabe Closures.

Generell definiere ich Delegaten recht selten (bis nie) selbst.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo ProgrammierTroll,

zum einen kommt es nicht auf ein rausgepicktes Kriterium an, sondern darauf, für welche Richtung die Kriterien in der Summe überwiegen. Zum anderen hast du das bewusste Kriterium m.E. falsch interpretiert. Das wird klar, wenn man die Beschreibung des Kriteriums liest:

Da ein geschachtelter Typ als Member des deklarierenden Typs behandelt wird, kann der geschachtelte Typ auf alle anderen Member des deklarierenden Typs zugreifen.

Es geht also darum, dass man so vorgehen sollte, wenn der innere Typ (hier die Deklaration des Delegaten) sinnvollerweise auf die nicht-öffentlichen Member des äußeren Typs (hier der Klasse) zugreifen sollte oder müsste. Bei einer Deklaration eines Delegaten greift man aber auf gar nichts zu, sondern spezifiziert nur den Rückgabetyp und die Parametertypen. Das Kriterium ist also gerade nicht erfüllt. Noch ein Grund mehr, Delegaten nicht in der Klasse zu definieren. Auch für dein Beispiel ein klares Nein, es sein denn, der Delegatentyp wird nur innerhalb der Klasse benötigt und soll nach außen nicht bekannt sein.

Um genau zu sein: Das Kriterium würde bei Delegaten überhaupt nur greifen, wenn mindestens einer der in der Deklaration des Delegaten verwendeten Typen ein nicht-öffentlicher geschachtelter Typ der Klasse ist, sagen wir ein privater Enumtyp. In diesem sehr unüblichen Fall besteht aber sowieso kein Zweifel, dass der Delegatentyp ebenfalls nur in der Klasse bekannt darf, denn sonnst würde man schon beim Compilieren einen Zugriffsfehler bekommen:

public class C
{
   private enum E { E1 }         // Achtung: private
   public delegate void D (E e); // Achtung: public
}

Fehlermeldung:
error CS0059: Inkonsistenter Zugriff: Parametertyp "C.E" ist weniger zugreifbar als Delegat "C.D"

public class C
{
   private enum E { E1 } // Achtung: private
}
delegate void D (E e);   // egal ob public oder nicht

Fehlermeldung:
error CS0246: Der Typ- oder Namespacename "E" konnte nicht gefunden werden.

herbivore

107 Beiträge seit 2011
vor 12 Jahren

Ok, die Argumentation kann ich nachvollziehen und akzeptieren.

Meine Interpretation war tatsächlich eine andere (dachte, es ginge um den Zugriff der Klasse auf den inneren Delegaten):

    public partial class Form1 : Form
    {
        private delegate void SetProgressBar(int value);

        public Form1()
        {
            InitializeComponent();
        }
    }

Wenn ich den Delegaten an dieser Stelle deklariere, dann schränke ich den Zugriff ein. Ich habe also nur Zugriff auf diesen innerhalb der partiellen Klassen.

    
        public delegate void SetProgressBar(int value);

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }

Hier ist der Delegat im gesamten Namespace zugreifbar. Es stellt sich also die Frage, ob die globale Verfügbarkeit gewünscht ist. Ich könnte mir durchaus Fälle vorstellen, wo man das nicht möchte und sich dann das "Wegkapseln" anbietet.

q.e.d.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo ProgrammierTroll,

ich habe den Startbeitrag erneut gelesen und dabei ist mir ein Fehler aufgefallen, auf den ich in meinem dortigen Moderationshinweis eingegangen bin (s.o.). Insgesamt scheint mir der Unterschied Schachtelung vs. Sichtbarkeit (Zugriffsmodifier) der springende Punkt zu sein.

Du redest darüber, ob man einen Delegatentyp, der nur innerhalb der Klasse benötigt wird, geschachtelt (und private) deklarieren sollte. Wenn diese Voraussetzung gegeben ist, macht das durchaus Sinn.

Die eigentliche Frage war m.E., ob man einen Delegatentyp, der zwar mit einer Klasse in (enger) Beziehung steht, den man aber auch außerhalb der Klasse benötigt, in der Klasse geschachtelt (und public) oder auf gleicher Ebene wie die Klasse deklarieren soll. Auf letzteres bezog sich ganz überwiegend die Argumentation in diesem Thread.

herbivore

107 Beiträge seit 2011
vor 12 Jahren

Die eigentliche Frage war m.E., ob man einen Delegatentyp, der zwar mit einer Klasse in (enger) Beziehung steht, den man aber auch außerhalb der Klasse benötigt, in der Klasse geschachtelt (und public) oder auf gleicher Ebene wie die Klasse deklarieren soll. Auf letzteres bezog sich ganz überwiegend die Argumentation in diesem Thread.

Ok, dann sind wir diesbezüglich einer Meinung. 👍

q.e.d.