Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable C# optimization of loop return value

Tags:

c#

.net

jit

csc

I have a method that returns an IEnumerable<T>. I call this method form two places, and in one of those places I do not do anything with the results.

It looks like the C# compiler removes the call to that method even if I decorate it with [MethodImpl(MethodImplOptions.NoOptimization)]. The code doesn't even enter the calling method. If I add .ToList() at the end, though, it is executed.

Is there a way to disable this optimization by the compiler/runtime? Looking at the ILDASM output, it looks like it's more of a runtime optimization because the call is there.

like image 392
Anže Vodovnik Avatar asked Mar 18 '23 07:03

Anže Vodovnik


1 Answers

It looks like the C# compiler removes the call to that method

No, it doesn't - this is just how iterator blocks work. The code inside the iterator block will only start being executed when MoveNext() is called for the first time. If you want to make sure that the whole method gets executed, you could just use:

SomeIteratorMethod().Count();

That will iterate over the whole sequence, throwing away results as it goes (as opposed to a call to ToList for example, which will

If you only want to get as far as the first yield statement, you can use

SomeIteratorMethod().Any();

If you want some code to always execute (e.g. parameter validation) but then the rest should be lazy, you need to split the method in two methods:

public IEnumerable<Foo> SomeIteratorMethod(string mustNotBeNull)
{
    if (mustNotBeNull == null)
    {
        throw ...
    }
    return SomeIteratorMethodImpl(mustNotBeNull);
}

private IEnumerable<Foo> SomeIteratorMethodImpl(string mustNotBeNull)
{
    ... yield new Foo()...
}

Or you could just stop using an iterator block, of course.

like image 143
Jon Skeet Avatar answered Mar 27 '23 11:03

Jon Skeet