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

禁用循环返回值的C#优化,c#,.net,jit,csc,C#,.net,Jit,Csc,我有一个方法返回一个IEnumerable。我从两个地方调用这个方法,其中一个地方我对结果不做任何处理 看起来C#编译器删除了对该方法的调用,即使我用[MethodImpl(methodimpoptions.NoOptimization)]修饰它。代码甚至没有输入调用方法。但是,如果我在末尾添加.ToList(),它将被执行 有没有办法通过编译器/运行时禁用此优化?查看ILDASM输出,它看起来更像是一个运行时优化,因为调用就在那里 看起来C#编译器删除了对该方法的调用 不,它不是-迭代器块就是

我有一个方法返回一个
IEnumerable
。我从两个地方调用这个方法,其中一个地方我对结果不做任何处理

看起来C#编译器删除了对该方法的调用,即使我用
[MethodImpl(methodimpoptions.NoOptimization)]
修饰它。代码甚至没有输入调用方法。但是,如果我在末尾添加
.ToList()
,它将被执行

有没有办法通过编译器/运行时禁用此优化?查看ILDASM输出,它看起来更像是一个运行时优化,因为调用就在那里

看起来C#编译器删除了对该方法的调用

不,它不是-迭代器块就是这样工作的。只有在第一次调用
MoveNext()
时,迭代器块中的代码才会开始执行。如果要确保执行整个方法,可以使用:

SomeIteratorMethod().Count();
这将遍历整个序列,并在执行过程中丢弃结果(例如,与调用
ToList
相反,它将

如果您只想得到第一个
yield
语句,可以使用

SomeIteratorMethod().Any();
如果希望某些代码始终执行(例如参数验证),但其余代码应该是惰性的,则需要将该方法拆分为两种方法:

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

private IEnumerable<Foo> SomeIteratorMethodImpl(string mustNotBeNull)
{
    ... yield new Foo()...
}
public IEnumerable SomeIteratorMethod(字符串不得为空)
{
如果(mustNotBeNull==null)
{
扔。。。
}
返回SomeIteratorMethodImpl(mustNotBeNull);
}
私有IEnumerable SomeIteratorMethodImpl(字符串不得为空)
{
…生成新的Foo()。。。
}

当然,您也可以停止使用迭代器块。

该方法看起来像什么?如果您使用
yield
,则生成的可枚举项将被惰性地计算。听起来该方法使用
yield
关键字返回惰性
IEnumerable
。添加
.ToList()
强制缓冲
IEnumerable
并执行方法。这是一个功能,而不是bug!事实上我使用的是一个yield关键字。我同意这是一个功能。我只是想知道是否有办法“禁用”它。我想最好的方法是不为此特定方法使用lazy?这不是一种优化。禁用它会改变执行流。如果lazy求值导致意外行为,那么您可能不应该使用它。听起来您应该在返回前将结果缓冲在列表/数组中。