如何解决c#产生并最终尝试
| 如果我有如下所示的协程,是否会调用finally块中的代码?public IEnumerator MyCoroutine(int input)
{
try
{
if(input > 10)
{
Console.WriteLine(\"Can\'t count that high.\");
yield break;
}
Console.WriteLine(\"Counting:\");
for(int i = 0; i < input; i++)
{
Console.WriteLine(i.ToString());
yield return null;
}
}
finally
{
Console.WriteLine(\"Finally!\");
}
}
解决方法
只要正确处理了迭代器/枚举器(称为“ 1”),就可以:
无论try块如何退出,控制总是传递给finally块。
http://msdn.microsoft.com/zh-CN/library/zwc8s4fz.aspx
但是,请注意确实会调用
Dispose()
,否则,您充其量只能得到意想不到的结果。有关此现象的更多信息以及需要注意的一些问题,请查看此博客文章:
产量和用途-您的处置可能不会被调用!
(感谢Scott B提供的链接,在答案中加入了答案,因为每个人似乎都错过了它)
另外:
yield return语句不能位于try-catch块内的任何位置。如果try块后跟有finally块,则可以将其放置在try块中。
http://msdn.microsoft.com/zh-CN/library/9k7k7cf0.aspx
,到目前为止,所有答案都省略了一个关键细节:如果且在执行yield return
的迭代器/枚举器上调用IDisposable.Dispose
时,将在包裹yield return
的finally
块中执行代码。如果外部代码在迭代器上调用GetEnumerator()
,然后调用MoveNext()
直到迭代器在finally
块内执行yield return
,然后外部代码不调用Dispose
放弃枚举器,则finally
块中的代码将不会运行。根据迭代器的工作方式,垃圾回收器可能会消灭它(尽管没有机会清理任何外部资源),或者它可能永久或半永久地以内存泄漏为根(如果发生这种情况,例如,它将lambda表达式附加到了长期存在的对象的事件处理程序上)。
请注意,尽管vb和c#在确保ensuring13ѭ循环将在枚举器上调用Dispose
方面都非常有用,但可以通过显式调用GetEnumerator()
来使用迭代器,并且某些代码可能无需调用Dispose()
就可以这样做。迭代器对此无能为力,但是任何编写迭代器的人都必须意识到这种可能性。
,根据文档,是的,finally中的代码将始终被调用。
由于您正在使用yield,因此直到您访问该方法返回的IEnumerator时,finally块才会执行。例如:
void Main()
{
var x = MyCoroutine(12);
//Console.WriteLines will happen when the following
//statement is executed
var y = x.MoveNext();
}
,如果您只是懒于添加Main()
等,请从此处获取代码,运行它并查看会发生什么:
最后的收益率和收益率
回应@Henk Holterman的评论
以下四个条件中的任何一个均有效:
* IEnumerable
* IEnumerable<T>
* IEnumerator
* IEnumerator<T>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。