我刚刚意识到,在我的代码中的某个地方,我在锁内部有一个return语句.哪一个是最好的?
1)
void example() { lock (mutex) { //... } return myData; }
2)
void example() { lock (mutex) { //... return myData; } }
我应该使用哪一个?
从本质上讲,这使代码更简单.单点退出是一个很好的理想,但我不会为了实现它而弯曲代码变形...如果替代方案是声明一个局部变量(在锁外),初始化它(在锁内)和然后返回它(在锁外),然后我会说锁中的一个简单的"返回foo"要简单得多.
为了显示IL的差异,让代码:
static class Program { static void Main() { } static readonly object sync = new object(); static int GetValue() { return 5; } static int ReturnInside() { lock (sync) { return GetValue(); } } static int ReturnOutside() { int val; lock (sync) { val = GetValue(); } return val; } }
(请注意,我很高兴地认为这ReturnInside
是一个更简单/更清洁的C#)
看看IL(发布模式等):
.method private hidebysig static int32 ReturnInside() cil managed { .maxstack 2 .locals init ( [0] int32 CS$1$0000, [1] object CS$2$0001) L_0000: ldsfld object Program::sync L_0005: dup L_0006: stloc.1 L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object) L_000c: call int32 Program::GetValue() L_0011: stloc.0 L_0012: leave.s L_001b L_0014: ldloc.1 L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object) L_001a: endfinally L_001b: ldloc.0 L_001c: ret .try L_000c to L_0014 finally handler L_0014 to L_001b } method private hidebysig static int32 ReturnOutside() cil managed { .maxstack 2 .locals init ( [0] int32 val, [1] object CS$2$0000) L_0000: ldsfld object Program::sync L_0005: dup L_0006: stloc.1 L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object) L_000c: call int32 Program::GetValue() L_0011: stloc.0 L_0012: leave.s L_001b L_0014: ldloc.1 L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object) L_001a: endfinally L_001b: ldloc.0 L_001c: ret .try L_000c to L_0014 finally handler L_0014 to L_001b }
因此,在IL级别,他们[给予或采取一些名称]相同(我学到了一些东西;-p).因此,唯一明智的比较是局部编码风格的(高度主观)法则......我更喜欢ReturnInside
简单,但我不会对此感到兴奋.
它没有任何区别; 它们都被编译器翻译成同一个东西.
为了澄清,要么有效地翻译成具有以下语义的东西:
T myData; Monitor.Enter(mutex) try { myData= // something } finally { Monitor.Exit(mutex); } return myData;
我肯定会把回报放在锁内.否则,您冒着另一个线程进入锁定并在return语句之前修改变量的风险,因此使原始调用者收到的值与预期不同.
如果认为外面的锁看起来更好,但是如果你最终将代码改为:
return f(...)
如果需要在保持锁的情况下调用f(),那么它显然需要在锁内部,因此保持在锁内部返回以保持一致性是有意义的.