2010-05-06 12 views
5

Ich habe ein Stück Code, mit der folgenden Logik:Was tun bei Verwendung von Contract.Assert (true) und die Methode muss etwas zurückgeben?

//pseudo-code 
foreach (element in elementList) { 
    if (element is whatever) 
     return element; 
    } 
} 

In der Theorie gibt es immer ein Element, das, was auch immer ist, so dass diese Methode sollte keine Probleme bereiten. Auf jedem Fall habe ich eine Aussage am Ende des Verfahrens stellt nur sicher sein:

//pseudo-code 
foreach (element in elementList) { 
    if (element is whatever) 
     return element; 
    } 
} 

Contract.Assert(false, "Invalid state!"); 

Das Problem ist, dass diese Methode etwas zurückgeben muß, und der Compiler nicht, dass die Behauptung nicht versteht wird die Programmausführung unterbrechen. Vor der Verwendung von Verträgen habe ich in solchen Situationen eine Exception geworfen, die das Problem gelöst hat. Wie würden Sie das mit Contract.Assert() handhaben? Zurückgeben von Null oder Standard (element_type) nach dem Aufruf von Contract.Assert() in dem Wissen, dass es nie aufgerufen wird und den Compiler herunterfährt? Oder gibt es eine andere elegantere Art, dies zu tun?

Dank

+0

Wollen Sie damit sagen nicht 'Contract.Assert (false, "Invalid Zustand!");'? –

+0

Ja, habe ich. : facep: –

Antwort

2

könnten Sie gehen mit

var result = null; 
foreach (element in elementList) { 
    if (element is whatever) 
     result = element; 
     break; 
    } 
} 

Contract.Assert(result != null, "Invalid state!"); 
return result; 

Es eine Pause führt, aber es sieht Reiniger um die Rückkehr.

Noch sauberer wäre

return elementList.Where(e => e is whatever).First(); 

bearbeiten als @devoured wies die oben würde

Reiniger ohne wo

return elementList.First(e => e is whatever); 

Ende bearbeiten die ganze Hitliste

Das explodiert gerade, wenn nichts gefunden wird.

Aber wenn Sie wirklich die assert wünschen könnte es

var results = elementList.Where(e => e is whatever); 
Contract.Assert(results.Count() == 1, "Boo"); 
return results.First(); 

sein, aber das wird die ganze Liste iterieren.

+0

Über die Verwendung von LINQ zuerst, wird das die gesamte elementList ausführen, oder es stoppt die Suche nach mehr Elementen in dem Moment, in dem es die erste findet? –

+1

@devoured Ich denke, wie ich geschrieben habe, wird es die ganze Liste laufen. Aber vielleicht als 'elementList.First (e => e was auch immer)' (beachten Sie das Fehlen von 'Where') sollte bei der ersten aufhören. Aber ich habe es nicht getestet –

+0

Oooooooops.Ich habe die Schaltfläche "Antwort annehmen" falsch gewählt und Sie abgelehnt. Sie müssen Ihre Antwort bearbeiten, damit ich die Abstimmung ändern kann :( –

1

Ich denke, Sie wären besser mit einer Contract.Requires (d. H. Eine Vorbedingung) als eine Contract.Assert hier. Voraussetzung für Ihr Snippet ist, dass elementList mindestens ein Element enthält, für das die Bedingung gilt.

Sie sollten dies explizit sein, anstatt sich auf eine Assert(false) zu verlassen, die erfordert, dass der Leser den Rest der Funktion versteht und der Flusssteuerung folgt, um die Situationen abzuleiten, in denen die Assert(false) erreicht wird.

So würde ich umschreiben als:

//precondition (checked only in debug builds) 
Contract.Require(elementList.Where(e => e is whatever).Count > 0,"elementList requires at least one element meeting condition whatever"); 
//do work (throws in release builds, never reached in debug ones) 
return elementList.First(e => e is whatever); 
+0

-, so müssen Sie zweimal über die Liste iterieren ... und das ist nicht das Sahnehäubchen ... Sie verwenden sogar '.Count()> 0' (Eigenschaftsaufruf ist nicht möglich, da die Rückgabe von' .Where() ''IEnumerable ' ist, und dieser Typ hat keine Eigenschaft '.Count', sondern eine Erweiterungsmethode ... 'Enumerable.Count()'), das über das ganze Ergebnis iterieren muss - verwenden Sie stattdessen '.Any()' –

+0

Nein. Jemand versteht nicht, wie Verträge funktionieren.Wenn Geschwindigkeit wichtig ist, iteriert meine Antwort über die Liste höchstens einmal. Die Voraussetzung macht die Code lesbarer, hilft beim Debuggen und dient als Hinweis für den Optimierer. Es wird nicht im Produktionscode ausgeführt. –

+0

Nein. Jemand versteht nicht, wie Linq funktioniert (bitte lesen Sie http://stackoverflow.com/questions/305092/which-method-performs-better-any-vs-count-0), und dass die Eigenschaft 'Count' nicht existiert auf einem 'IEnumerable ' - dennoch ist die Ausführung von 'Contract.Require' eine Frage der Konfiguration (aka' Runtime Contract Checking': ** 'Full' **,' Pre und Post', ...). –