Dupe: return statement in a lock procedure: inside or outside
The title is a little misleading. I know that you can do it, but I\'m wondering about
Yes, but why not use Dequeue?
Remember lock is simply shorthand for essentially something along the lines of:
try
{
Monitor.Enter(QueueModifierLockObject);
DownloadFile toReturn = queue.Dequeue();
return toReturn;
}
finally
{
Monitor.Exit(QueueModifierLockObject);
}
The C# compiler will move the return statement outside of the try/finally
that is created for the lock
statement. Both of your examples are identical in terms of the IL that the compiler will emit for them.
Here is a simple example proving that:
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;
}
}
The code above gets compiled to the following:
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;
}
}
As you can see, the compiler has taken the libery of moving the return statement in Foo
outside of the try/finally
.
I believe the IL would be identical... I'd have to test it to be fer sure, but the lock statement generates a try finally in the IL, and the return would trigger the finally (with the release) BEFORE the stack frame closes and returns to the caller anyway, so...