Dupe: return statement in a lock procedure: inside or outside
标题有点误导。我知道你可以做到,但我想知道性能影响。
考虑这两个代码块。 (没有错误处理)
此块在锁定
之外有return
public DownloadFile Dequeue()
{
DownloadFile toReturn = null;
lock (QueueModifierLockObject)
{
toReturn = queue[0];
queue.RemoveAt(0);
}
return toReturn;
}
此块在锁
中包含return
语句
public DownloadFile Dequeue()
{
lock (QueueModifierLockObject)
{
DownloadFile toReturn = queue[0];
queue.RemoveAt(0);
return toReturn;
}
}
代码有什么不同吗?我理解性能差异(如果有的话)会很小,但我特别想知道lock
释放的顺序是否存在差异。
答案 0 :(得分:24)
C#编译器会将return语句移到为try/finally
语句创建的lock
之外。您的两个示例在编译器将为其发出的IL方面是相同的。
这是一个证明:
的简单示例class Example
{
static Object obj = new Object();
static int Foo()
{
lock (obj)
{
Console.WriteLine("Foo");
return 1;
}
}
static int Bar()
{
lock (obj)
{
Console.WriteLine("Bar");
}
return 2;
}
}
上面的代码被编译为以下代码:
internal class Example
{
private static object obj;
static Example()
{
obj = new object();
return;
}
public Example()
{
base..ctor();
return;
}
private static int Bar()
{
int CS$1$0000;
object CS$2$0001;
Monitor.Enter(CS$2$0001 = obj);
Label_000E:
try
{
Console.WriteLine("Bar");
goto Label_0025;
}
finally
{
Label_001D:
Monitor.Exit(CS$2$0001);
}
Label_0025:
CS$1$0000 = 2;
Label_002A:
return CS$1$0000;
}
private static int Foo()
{
int CS$1$0000;
object CS$2$0001;
Monitor.Enter(CS$2$0001 = obj);
Label_000E:
try
{
Console.WriteLine("Foo");
CS$1$0000 = 1;
goto Label_0026;
}
finally
{
Label_001E:
Monitor.Exit(CS$2$0001);
}
Label_0026:
return CS$1$0000;
}
}
正如您所看到的,编译器采用了在Foo
之外的try/finally
中移动return语句的库。
答案 1 :(得分:2)
我相信IL会是相同的...我必须测试它才能确定,但是lock语句最终会在IL中生成一次尝试,并且返回将触发finally(发布时)BEFORE堆栈框架关闭并返回到调用者,所以......
答案 2 :(得分:0)
是的,但为什么不使用Dequeue?
记住锁只是简单的简写,基本上是:
try
{
Monitor.Enter(QueueModifierLockObject);
DownloadFile toReturn = queue.Dequeue();
return toReturn;
}
finally
{
Monitor.Exit(QueueModifierLockObject);
}