Anonyme innere Klassen in C #?

8

Gibt es so etwas wie anonyme innere Klassen (in Java verwendet) in C #?

Ich erkläre, wofür ich es verwenden würde: Ich deklariere und initialisiere das Feld vom Typ IDictionary<Person, Account> und ich muss das benutzerdefinierte IEqualityComparer<Person> schreiben. Das liegt daran, dass zwei Personen vom IDictionary als gleich behandelt werden sollen, wenn sie gleiche Namen und IDs haben (nicht nur IDs wie standardmäßig). Ich werde dieses IEqualityComparer<Person> nirgendwo sonst im Code brauchen.

Also muss ich eine neue Klasse deklarieren, die IEqualityComparer<Person> implementiert, um dies zu tun? In Java würde ich anonyme Klasse verwenden, etwas in der Art (das ist gemischte C # -Java-Syntax, nur um zu zeigen, welche Funktionalität ich suche):

%Vor%

Ist so etwas in C #? Ich bin zu faul, um jedes Mal, wenn ich etwas brauche, eine neue Klasse zu schreiben.

Hinweis: Dies ist Syntaxfrage. Ich weiß, wie man es schreibt, aber ich möchte wissen, ob es möglich ist, den Code kürzer zu machen.

-------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------

BEARBEITEN: Wie codierst du selbst ähnliche Fälle? Erstellst du eine neue Klasse, um die Schnittstelle zu implementieren oder was machst du? Vielleicht hast du einen Trick, den ich mag.

BEARBEITEN Was ist mit der zukünftigen Unterstützung für anonyme Klassen wie die in Java? Hast du etwas davon gehört?

BEARBEITEN: Nun, ich sehe, dass ich meinen eigentlichen Code bereitstellen muss - nicht nur ein Beispiel. Das liegt daran, dass ich nicht weiß, ob es mit Jons Skeets Lösung funktionieren wird.

Der eigentliche Grund, warum ich nicht nur Equals(object) und GetHashCode in der Klasse selbst implementiere, ist, dass es sich um eine Klasse (Entität) handelt, die vom E-R-Framework aus dem Modelldiagramm generiert wird. Wenn ich es in der Klasse selbst implementiere, würde mein Code jedes Mal aus der Klasse (Entität) gelöscht werden, wenn ich das Modell aus der Datenbank aktualisiere (mit der Funktion "Update von der Datenbank"). Die Klasse heißt eigentlich Font nicht Person . Es hat diese Eigenschaften:

%Vor%

Dabei ist Color eine andere Klasse (Entität), die aus der Datenbank generiert wird.

Dies sind Eigenschaften von Farbe:

%Vor%

Also kann ich weder Schriftart noch Farbe ändern (wenn ich diese Änderungen nicht jedes Mal neu schreiben möchte, wenn ich die Datenbank ändere) Ich möchte, dass% cos_de%:

%Vor%

Und der Vergleicher Dictionary sollte sicherstellen, dass zwei Zeichensätze genau dann als gleich betrachtet werden, wenn alle oben aufgeführten Eigenschaften (außer SomeEqualityComparer ) gleich sind. Bei der letzten Eigenschaft Id werden zwei Foreground s als gleich betrachtet, wenn alle ihre Eigenschaften (außer Color ) gleich sind.

Wenn ich jetzt eine Lösung verwende, die Jon Skeet mir freundlicherweise empfohlen hat, bin ich mir nicht sicher, ob das gewährleistet werden kann. Wenn ich etwas wie:

benutzt habe %Vor%

Ich vermute, dass anonyme Typen Id für alle Eigenschaften aufrufen, wenn ihr Equals(object) aufgerufen wird. Da ich jedoch Equals(object) s Color nicht überschreiben kann, würde ich Equals(object) s nicht wie gewünscht vergleichen (mit allen Eigenschaften außer Color ), also würde auch die Gleichheit von Id s falsch getestet werden. Habe ich Recht?

    
drasto 22.08.2010, 20:30
quelle

7 Antworten

2

In Ihrer letzten Bearbeitung erwähnen Sie, dass Sie Equals und GetHashCode nicht implementieren, weil der Code für Ihre Klassen automatisch generiert wird und Sie diesen Code nicht bei jeder Neugenerierung erneut implementieren müssen der Code.

Das ist eines der Szenarien, für die partielle Klassen in C # eingeführt wurden

Viele Codegenerierungstools generieren Klassen mit dem Schlüsselwort partially, damit Sie diese Funktion nutzen können. Überprüfen Sie, ob die für den Code generierten Klassen partiell sind.

In einer separaten Datei (oder Dateien), die nicht überschrieben werden, wenn Sie den Code in derselben Assembly neu generieren, könnten Sie etwas wie folgt haben:

%Vor%     
Dr. Wily's Apprentice 23.08.2010, 21:24
quelle
13

Ich habe eine Klasse ProjectionEqualityComparer , die Sie in MiscUtil verwenden können. Sie würden Code wie folgt verwenden:

%Vor%

Dies nutzt die Tatsache, dass anonyme Typen geeignete Gleichheitskonzepte enthalten. Wenn% code% gefragt wird, zwei Personen auf Gleichheit zu prüfen, projiziert sie jeweils auf den anonymen Typ und vergleicht diese Instanzen. Wenn es nach einem Hashcode gefragt wird, führt es die Projektion aus und fragt nach seinem Hash-Code.

BEARBEITEN: Um Ihr Farbproblem zu lösen, haben Sie recht: Wenn ProjectionEqualityComparer Equals / GetHashCode nicht auf die von Ihnen gewünschte Weise überschreibt, können Sie es nicht direkt verwenden. Sie können dies jedoch stattdessen tun:

%Vor%

Wenn Sie den Typ Color in Bezug auf Eigenschaften ändern können, wäre es einfacher, wenn Sie ihm eine von den anderen generierte ARGB-Eigenschaft zuweisen könnten, so dass Sie schreiben könnten:

%Vor%

Das ist ziemlich hässlich, aber es sollte funktionieren ...

    
Jon Skeet 22.08.2010 20:38
quelle
2

Nein, ist es nicht. Es gibt anonyme Typen, z. B.

%Vor%

aber sie sind sehr begrenzt und enthalten nur schreibgeschützte Eigenschaften und keine Methoden.

    
Ben Robinson 22.08.2010 20:38
quelle
2

Die wörtliche Antwort ist, dass nein, C # keine anonymen inneren Klassen hat, weil Java diese hinzugefügt hat, um seinen Mangel an erstklassigen Funktionen, die C # hat, zu umgehen. Um Ihr Problem zu lösen, können Sie einfach IEquatable<Person> für Ihre Klasse Person implementieren, und dann wird IDictionary diese automatisch verwenden. Das ist die gängigste Lösung für dieses Problem und funktioniert so lange wie Ihr OK mit dem Prozess für den Vergleich von Personen, die in diese Klasse gebacken werden.

Wenn Sie möchten, dass die Vergleichs- / Gleichheitslogik nicht direkt an Person gebunden ist, können Sie in den meisten Auflistungen in .NET ein Comparison<T> -Objekt übergeben (was ein Delegat und keine Schnittstelle ist) schöne In-Place-Sortierlogik. Um beispielsweise eine Personenliste nach Namen zu sortieren, können Sie Folgendes tun:

%Vor%

Leider hat Dictionary nichts, was einer Gleichheitsfunktion ähnelt. In .NET 4.0 scheint die Bestandsantwort EqualityComparer<T> zu überschreiben:

%Vor%

Jedes Mal, wenn Sie einen Vergleich durchführen müssen, müssen Sie eine neue Klasse definieren. Was ich tun würde, ist eine generische, die eine Funktion hat:

%Vor%

Fügen Sie eine kleine Hilfsklasse hinzu:

%Vor%

Und dann wird Ihre Lösung:

%Vor%

Noch kürzer als in Java.

    
munificent 22.08.2010 20:56
quelle
1

Der nächste, den Sie bekommen, ist anonyme Typen , wie Sie es sehen würden ein LINQ-Ausdruck Ein kurzes Beispiel aus dem Link:

%Vor%

Definitiv nicht das, wonach Sie suchen. Ich habe auch von zukünftiger Unterstützung für anonyme Klassen in C # nicht gehört.

    
David Hoerster 22.08.2010 20:35
quelle
0

Sie können die Implementierung der Schnittstelle an einer Stelle definieren, 1 Klasse, die Schnittstelle zu Ihrer gewünschten Implementierungsklasse in Ihrem bevorzugten IOC-Framework zuordnen und nicht über die Instantiierung einer anonymen Implementierung mit einmaliger Verwendung nachdenken.

    
Tahbaza 22.08.2010 20:40
quelle
0

Nein, zu der Zeit, als diese Frage ursprünglich geschrieben wurde (C # 3.0), gibt es keine.

    
Richard J. Ross III 22.08.2010 20:32
quelle

Tags und Links