我可以在锁内放一个return语句

Dev*_*inB 15 c# locking

Dupe: 在锁定程序中返回声明:内部或外部

标题有点误导.我知道你可以做到,但我想知道性能影响.

考虑这两个代码块.(没有错误处理)

这个区块有return锁外

 public DownloadFile Dequeue()
 {
     DownloadFile toReturn = null;
     lock (QueueModifierLockObject)
     {
         toReturn = queue[0];
         queue.RemoveAt(0);
     }
     return toReturn;
 }
Run Code Online (Sandbox Code Playgroud)

该块具有锁return语句

 public DownloadFile Dequeue()
 {
     lock (QueueModifierLockObject)
     {
         DownloadFile toReturn = queue[0];
         queue.RemoveAt(0);

         return toReturn;
     }
 }
Run Code Online (Sandbox Code Playgroud)

代码有什么不同吗?我理解性能差异(如果有的话)是最小的,但我特别想知道lock获取释放的顺序是否会有所不同.

And*_*are 25

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码被编译为以下代码:

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;
        }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,编译器已经采用了将返回语句移动到Foo外部的libery try/finally.

  • 确实.如果你去看看生成的IL,你会明白为什么我们这样做.您只能通过特殊的"离开"指令离开受保护区域,该指令知道如何清理异常处理goo(当然,通过抛出异常).你不能做普通的分支或退出受保护的区域.因此,我们必须从受保护区域生成叶子到在区域外生成的返回. (8认同)