2009-07-19 10 views
4

Ich schreibe eine Methode, die einige Parameter überprüfen muss und wenn sie validiert sind, ein IEnumerable zurückgeben. Z.B.Benannte Iterator & Exceptions

public static IEnumerable<double> GetEnum(int param) 
{ 
    if (!IsValidParameter(param)) 
    { 
     throw new Exception(); 
    } 

    while(true) 
    { 
     yield return 5.0; 
    } 
} 

Ich glaube jedoch, wegen lazy evaluation, wenn ich mit schlechten Parameter meiner Unit-Tests laufen, aber eine der IEnumerable Methoden noch nicht aufrufen, wird die Ausnahme nicht geworfen.

[Test] 
[ExpectedException(typeof(Exception))] 
void Test() 
{ 
    var ie = GetEnum(bad_param); 
} 

Ich kann Dinge beheben, indem Sie die IEnumerable in einer anderen Funktion Aufbau (sagen Foo), dann Parameter überprüfen in GetEnum und rufen Foo aber gibt es eine Lösung, ohne dass mehrere Funktionen erstellen zu müssen?

Cheers, Jurgen

Antwort

9

Aufgrund wie Iterator Blöcke definiert sind, müssen Sie derzeit zwei Methoden, um dies zu erreichen:

public static IEnumerable<double> GetEnum(int param) { 
    if (!IsValidParameter(param)) { 
     throw new Exception(); 
    } 
    return GetEnumCore(param); 
} 
private static IEnumerable<double> GetEnumCore(int param) { 
    while(true) { 
     yield return 5.0; 
    } 
} 

Nur der Iteratorblock (GetEnumCore) verschoben wird; GetEnum läuft sofort und führt Ihre Überprüfungen durch.

+0

Ich fragte mich, ob der Compiler schlau genug war, um beide Methoden auf einen einzelnen Iteratorblock zu reduzieren. Danke für den Tipp, Marc. –

2

Könnten Sie vielleicht initiieren nur die Iteration des zugrunde liegenden Enumerator verwenden?

[Test] 
[ExpectedException(typeof(Exception))] 
void Test() 
{ 
    var ie = GetEnum(bad_param); 
    var en = ie.GetEnumerator(); 
    en.MoveNext(); 
} 
+0

Ich verstehe dieses faule Verhalten des Enumerators, gibt es keine Möglichkeit, die Ausnahme vor zu werfen? Sprich im Konstruktor der Klasse, die für die benannte Iteration generiert wird? – Jurgen

2

Solange Sie nicht mit dem Aufzählen beginnen, wird Ihre Methode nie aufgerufen werden. Sie könnten versuchen, in Ihrem Test aufzählt:

var ie = GetEnum(bad_param).First();