我有一个返回IEnumerable<T>
的方法。我把这个方法称为两个地方,在其中一个地方我没有对结果做任何事情。
看起来C#编译器删除了对该方法的调用,即使我用[MethodImpl(MethodImplOptions.NoOptimization)]
进行装饰也是如此。代码甚至没有进入调用方法。但是,如果我在最后添加.ToList()
,则执行它。
有没有办法通过编译器/运行时禁用此优化?查看ILDASM输出,它看起来更像是运行时优化,因为调用就在那里。
答案 0 :(得分:7)
看起来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()...
}
或者你当然可以停止使用迭代器块。