c# - 在 try 块中返回的伪代码是什么?
问题描述
以下代码
class Animal : IDisposable
{
static string Invoker()
{
using (Animal a = new Animal())
{
return a.Greeting();
}
}
public void Dispose()
{
Console.WriteLine("Disposed");
}
public string Greeting()
{
return "Hello World";
}
static void Main()
{
Console.WriteLine("Before");
Console.WriteLine(Invoker());
Console.WriteLine("After");
}
}
生产
Before
Disposed
Hello World
After
因为这个输出在Disposed
之前Hello World
,我猜
using (Animal a = new Animal())
{
return a.Greeting();
}
相当于
Animal a = new Animal();
string buffer = null;
try
{
buffer = a.Greeting();
}
finally
{
a.Dispose();
return buffer;
}
但是,这显然是不正确的,因为以下错误消息:
控制不能离开 finally 块的主体。
那么我的最终猜测就变成了如下。
Animal a = new Animal();
string buffer = null;
try
{
buffer = a.Greeting();
return buffer;
}
finally
{
a.Dispose();
//return buffer;
}
但是,我仍然很困惑Dispose()
如果return buffer
在执行顺序中首先调用,如何调用。尽早离开函数体使得Dispose()
必须由某些东西(其他代理或线程或垃圾收集器或我不详细了解的任何隐藏机制)调用。这是我的想象。另外,如果return buffer
先出现,那么输出应该是
Before
Hello World
Disposed
After
问题
你能告诉我编译器或内部机制是如何调用的Dispose()
,而return buffer
先到先得导致过早地离开函数体Invoker
吗?
解决方案
语言规范说这种形式的 using 语句:
using (ResourceType resource = expression) statement
相当于:
{
ResourceType resource = expression;
try {
statement;
}
finally {
((IDisposable)resource).Dispose();
}
}
因此,您的 using 语句等效于:
{
Animal a = new Animal();
try {
return a.Greeting();
} finally {
a.Dispose();
}
}
我只能猜测为什么你认为这是违反直觉的。可能是因为你认为finally
不会因为return
? 好吧,规范还规定:
块的语句
finally
总是在控制离开try
语句时执行。无论控制转移是正常执行的结果,还是执行break
,continue
,goto
, orreturn
语句的结果,还是从语句中传播异常的结果,都是如此try
。
推荐阅读
- android - 启用开关时如何更改 SwitchPreference 文本颜色?
- pyspark - 在 pyspark 中拆分和爆炸;Py4JJavaError:java.lang.OutOfMemoryError:Java 堆空间
- excel - 简单复制粘贴宏上的 VBA 内存不足错误
- sql - DB2:实现 LAG ROWS UNBOUNDED PRECEDING 和 UNBOUNDED FOLLOWING
- google-sheets - 电子邮件字段显示为来自 google sheet =importhtml() 函数的 [电子邮件保护]
- c++ - X11不会开窗
- c - 使用 c 语言的带有最少括号数的中缀前缀
- sql - “无法识别数值''” - 哪一列?
- firebase - 具有统一性的 Firebase Auth 在每次启动时都会创建新用户
- python - 将丢失的数据从一个配置文件复制到另一个