我有一个返回IEnumerable<T>的方法。我从两个地方调用这个方法,在其中一个地方,我对结果不做任何处理。
看起来,即使我用[MethodImpl(MethodImplOptions.NoOptimization)]修饰它,c编译器也会删除对该方法的调用。代码甚至没有输入调用方法。不过,如果我在末尾加上.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()...
}

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

09-20 22:38