2013-05-14 1 views
5

Ich arbeite innerhalb einer Methode, die eine Reihe von Validierungsprüfungen durchführt und sollte eine dieser Prüfungen fehlschlagen, ruft sie eine Action<string> auf, um einen gemeinsamen Ablehnungscode auszuführen. Die Einrichtung ist so etwas wie dies:Rückkehr von der übergeordneten Methode innerhalb der Aktion <string>

public void ValidationMethod() { 
    Action<string> rejectionRoutine = (rejectionDescription) => { 
     // do something with the reject description 
     // other common code 
    }; 

    if (condition != requiredValue) { 
     rejectionRoutine("Condition check failed"); 
     // I currently have to put `return` here following every failed check 
    } 

    // many more checks following this 
} 

In diesem System einmal eine Überprüfung Validierung fehlgeschlagen ich keine Notwendigkeit, den Rest zu validieren, ich möchte nur die gemeinsame Ablehnung Code innerhalb der Aktion auszuführen, und das Verfahren zu beenden . Derzeit, um dies zu tun, ich nur return in der nächsten Zeile nach einem Anruf an . Ich frage mich, ob es eine Möglichkeit gibt, die Möglichkeit zu integrieren, die Ausführung der übergeordneten Methode innerhalb der Action zurückzugeben oder zu beenden?

Ich weiß, das ist ein bisschen pingelig, aber ich denke, es ist besser für die Erweiterbarkeit weiter unten auf der Straße, wenn jemand andere zusätzliche Validierungsprüfungen hinzufügen muss (sie müssen sich nicht um die Rückgabe kümmern place) sowie das gemeinsame Verhalten der Endausführung innerhalb des Codes einzufügen, der in diesen Fällen üblich ist.

Antwort

6

Eine Möglichkeit, den Code der Reinigung alle der Kontrollen in einer Sammlung wäre ein bisschen bis zu extrapolieren:

wichtig
Dictionary<Func<bool>, string> checks = new Dictionary<Func<bool>, string>() 
{ 
    {()=> condition != requiredValue, "Condition check failed"}, 
    {()=> otherCondition != otherRequiredValue, "Other condition check failed"}, 
    {()=> thirdCondition != thirdRequiredValue, "Third condition check failed"}, 
}; 

Wenn es für die Prüfungen in einer bestimmten Reihenfolge ausgeführt werden (dieser Code hat eine unvorhersehbare Reihenfolge), dann möchten Sie stattdessen etwas wie eine List<Tuple<Func<bool>, string>> verwenden.

var checks = new List<Tuple<Func<bool>, string>>() 
{ 
    Tuple.Create<Func<bool>, string>(()=> condition != requiredValue 
     , "Condition check failed"), 
    Tuple.Create<Func<bool>, string>(()=> otherCondition != otherRequiredValue 
     , "Other condition check failed"), 
    Tuple.Create<Func<bool>, string>(()=> thirdCondition != thirdRequiredValue 
     , "Third condition check failed"), 
}; 

Anschließend können Sie LINQ verwenden, um die Validierung zu tun:

var failedCheck = checks.FirstOrDefault(check => check.Item1()); 
if (failedCheck != null) 
    rejectionRoutine(failedCheck.Item2); 
+0

Ahhh Servy, große Köpfe denken gleich.Ich habe Code geschrieben, der fast identisch war, bevor ich ein paar Stellen fand, wo es keinen Sinn ergab. Es gibt einige Überprüfungen, die Ausnahmen auslösen, wenn sie ausgewertet werden, wenn eine vorherige Überprüfung abgeschlossen sein sollte. Ie. check1 ist value! = null, check2 könnte etwas mit Wert machen, vorausgesetzt, dass es nicht null sein kann, wenn wir so weit gekommen sind –

+0

@JesseCarter Dann, wie ich am Ende gesagt habe, müssen Sie eine 'List verwenden , Zeichenfolge >> '. Es ist nur ein bisschen mehr Code. – Servy

+0

Vielleicht bin ich verwirrt über die Art, wie der Bool in der Func ausgewertet wird? Wird die tatsächliche Bewertung des Bool-Wertes aufgeschoben, bis der Func aufgerufen wird? Ich nahm an, dass es ausgewertet würde, sobald der Func erstellt wurde –

1

Es macht keinen Sinn, von der Caller-Methode innerhalb eines Lambda-Ausdrucks zurückzukehren.
(was ist, wenn Sie es nach der Methode aufrufen, läuft fertig?)

Stattdessen Sie es zu einem Func<string, Whatever> und Rück seinen Wert ändern können:

return rejectionRoutine("Condition check failed"); 
+0

Die Aktion lebt lokal innerhalb des Verfahrens, so sehe ich nicht, wie es, wenn die Methode ausgeführt wurde, beendet genannt werden könnte? Wenn ich etwas von einem Func zurückgebe, müsste ich immer noch einen if (returnValue == etwas) nach jedem Check zurückgeben. Oder fehlt mir bei diesem Ansatz etwas? –

+0

@JesseCarter: Nichts hindert Sie daran, den Delegierten außerhalb der Methode verfügbar zu machen. Ich bin mir nicht sicher was du meinst. – SLaks

+0

Ich habe das Codebeispiel in meiner Frage bearbeitet, die Aktion existiert nur im Rahmen der umgebenden Validierungsmethode. Ich sehe nicht, wie es irgendwo anders genannt werden könnte, außer innerhalb dieser Methode. –

0

Als Alternative zu SLaks Lösung auch möglich Werfen Sie eine Ausnahme in Ihr rejectionRoutine, wenn Ihr Entwurf es erlaubt.

+0

Leider denke ich nicht, dass das Werfen einer Ausnahme zum aktuellen Design passt. Danke für den Gedanken aber –

+3

Ausnahmen sollten nicht für den normalen Kontrollfluss verwendet werden; Sie sollten für Ausnahmesituationen verwendet werden. – Servy

+0

Meine Gedanken genau Servy und ich bin sicher, das wäre der Konsens in meinem Code-Review, wenn ich es so machen würde –