Laden...

abstracte Klasse, allgemeinen Konstruktor erzwingen, analog zu Enumerable.Empty<T>()

Letzter Beitrag vor 4 Jahren 9 Posts 602 Views
abstracte Klasse, allgemeinen Konstruktor erzwingen, analog zu Enumerable.Empty<T>()

Hallo,

ich habe eine abstracte Klasse wie folgt:


public abstract class EvaluationResult
{
    public bool IsEvaluationValid { get; }
        
    public bool TestPassed { get; }

    public EvaluationResult(bool testPassed, bool isEvaluationValid)
    {
        TestPassed = testPassed;
        IsEvaluationValid = isEvaluationValid;
    }
}

Von dieser leite ich andere Result-Klassen ab, die neben den beiden Properies noch andere haben, in denen irgendwelche Erbebniswerte stehen.

Nun möchte ich für den Fall, dass keine Bewertung durchgeführt werden konnte, weil beispielsweise die Eingabeparameter der Bewertungsfunktion nicht sinnvoll sind, eine abgeleitete Klasse mit


IsEvaluationValid = false 

zurück geben und dazu eine ensprechende statische Methode


DerivedResult.Invalid()

haben, vergleichbar mit Enumerable.Empty<T>(), nur das T nur eine Subklasse von EvaluationREsult sein darf. Wie stelle ich das an?

Grüße, Alex

Final no hay nada más

Enumerable.Empty<T>() ist kein Konstruktor, sondern eine statische Methode.

Und im Source-Code von Enumerable.Empty sieht man, daß dort eine Instanz (leeres Array) gekapselt in einer eigenen Klasse (EmptyEnumerable<TElement>) zurückgegeben wird.

Brauchst du denn wirklich für deinen Fall eine generische Methode (bzw. Instanz)?
M.E. reicht bei dir einfach, daß du von EvaluationResult eine Klasse EmptyResult ableitest und davon dann ein (statisches) Objekt zurückgibst.

Hallo Th69,

danke für deine Antwort. Das mit dem Kontruktor war etwa unglücklich ausgedrückt. Die Implementierung von Enumerable.Empty hatte ich mir angeschaut.

Ich habe verschiedene Bewertungsmethoden, die verschiedene Ergebnisse zurückgeben. Deshalb ist das mit der einen invaliden Klasse bisschen schwierig. Ich hab es jetzt erst mal so gelöst, dass ich für jede Result-Klasse eine statische Methode in einer statischen Klasse habe, die mir das gewünschte Objekt liefert. st nicht optimal, aber für meinen Fall passt das so.

Final no hay nada más

Ich hab es jetzt erst mal so gelöst, dass ich für jede Result-Klasse eine statische Methode in einer statischen Klasse habe

Eine andere Möglichkeit hast Du auch nicht, sowas wie ein statisches Interface gibt es nicht.

Du müsstest also ganz umdenken, z.B. indem Du eine Factory erstellst, die die ein gültiges und ein ungültiges Objekt bauen kann. Die musst Du dann natürlich für jede deiner Klassen implementieren.
Oder Du verwendest Reflection (also ActivatorUtilities.CreateInstance), was ich persönlich aber für sehr ungünstig halte, da Du dann eine "heimliche Übereinkunft" hast, welche Parameter jede Klasse haben darf.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

Ich verstehe ehrlich gesagt die Klasse nicht. Was soll sie denn ausdrücken?
Kann sie valide sein, wenn ein Test niemals erfolgreich war?

Wenns logisch eindeutige Zustände sind, dann würde ich viel eher ein Enum verwenden.

Mich erinnert das ein bisschen an ValidationResult.
Das Ding soll ja sowohl einen gültigen als auch einen ungültigen Zustand darstellen können.
Und hier kommen scheinbar mehrere Ableitungen mit Daten je Zustand, die alle ein ähnliches Verhalten zeigen sollen.

Allerdings - wäre es dann nicht klüger, den Zustand (Valide vs. Invalide) von den Daten zu trennen?
Wie Abt schon sagt, ein Enum oder ein Bool und daneben dann die restlichen Daten - zumindest soweit sie gefüllt werden können oder null.

Z.B. heute erst hab ich bei einer Web-API von diesem Vorgehen profitiert:
Es gibt viele verschiedene Responses, die Daten sehen völlig anders aus, aber ich konnte mich immer darauf verlassen, dass es einen Status und eine Meldung dazu gibt, immer an der selben Stelle.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

Hallo Abt,

Beispielsweise verrechne ich in der Bewertung zwei Messsignale miteinander. Wenn diese sich aber gar nicht zeitlich überlappen, weil der Benutzer die falschen Daten ausgewählt hat, dann kann ich kein valides Ergebnis erzeugen. Ansonsten kann es sein, dass das Ergebnis berechnet, aber der Test nicht bestanden wurde. Dann wäre das Ergebnis valide, aber negativ. Ich bin da für Vorschlage sehr offen, wenn du das anders/besser lösen würdest.

Edit: @Palladin: Meinst du eine Art TryEvaluate-Methode mit out-Parameter, wie das beim numerischen Parsen von strings verwendet wird?

Grüße, Alex

Final no hay nada más

ill_son, mit Deiner Erklärung macht das nun etwas mehr Sinn und erinnert tatsächlich etwas an ValidationResult.
Da kannst Du dann - wie Palladin sagt wirklich einfach mit statischen Methoden arbeiten, was ein legitimer Zweck ist und durchaus üblich.

Bekannt ist das Verhalten auch vom ModelBinder, zB ModelBinderResult.Success().
Das Nutzen eines struct ist hier durchaus sinnvoll.

Danke nochmal.

Final no hay nada más