简体   繁体   English

禁用循环返回值的C#优化

[英]Disable C# optimization of loop return value

I have a method that returns an IEnumerable<T> . 我有一个返回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)] . 看起来C#编译器删除了对该方法的调用,即使我用[MethodImpl(MethodImplOptions.NoOptimization)]装饰它也是如此。 The code doesn't even enter the calling method. 代码甚至没有进入调用方法。 If I add .ToList() at the end, though, it is executed. 但是,如果我在末尾添加.ToList() ,它就会被执行。

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. 查看ILDASM输出,看起来它更像是运行时优化,因为调用就在那里。

It looks like the C# compiler removes the call to that method 看起来C#编译器删除了对该方法的调用

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. 迭代器块中的代码只有在第一次MoveNext()时才会开始执行。 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 这将迭代整个序列,随着它的结果丢弃结果(而不是调用ToList ,例如,将会

If you only want to get as far as the first yield statement, you can use 如果您只想获得第一个yield语句,则可以使用

SomeIteratorMethod().Any();

If you want some code to always execute (eg 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. 或者你当然可以停止使用迭代器块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM