views:

104

answers:

3

Hi,

I am writing a method which needs to check some parameters and if they are validated return an IEnumerable. E.g.

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

    while(true)
    {
        yield return 5.0;
    }
}

However, I believe because of lazy evaluation, when I run my unit tests with bad parameters, but don't call any of the IEnumerable methods yet, the Exception is not thrown.

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

I can fix things by building the IEnumerable in another function (say Foo), then check parameters in GetEnum and call Foo but is there a solution without having to create multiple functions?

Cheers, Jurgen

+2  A: 

Could you maybe just initiate the iteration using the underlying enumerator?

[Test]
[ExpectedException(typeof(Exception))]
void Test()
{
    var ie = GetEnum(bad_param);
    var en = ie.GetEnumerator();
    en.MoveNext();
}
Matt Hamilton
I understand this lazy behavior of the enumerator, is there no way to throw the exception before? Say in the constructor of the class that is generated for the named iteration?
Jurgen
+2  A: 

As long as you don't start enumerating your method will never be called. You could try enumerating in your test:

var ie = GetEnum(bad_param).First();
Darin Dimitrov
+8  A: 

Due to how iterator blocks are defined, you currently need two methods to achieve this:

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;
    }
}

Only the iterator block (GetEnumCore) is deferred; GetEnum runs immediately, performing your checks.

Marc Gravell
I actually wondered whether the compiler was smart enough to reduce both methods down into a single iterator block. Thanks for the tip, Marc.
Matt Hamilton