return ステートメントはロックの内側に置くべきか外側に置くべきか? 質問する

return ステートメントはロックの内側に置くべきか外側に置くべきか? 質問する

コード内のどこかに、ロックの内側と外側に return ステートメントがあることに気付きました。どちらが最適でしょうか?

1)

void example()
{
    lock (mutex)
    {
    //...
    }
    return myData;
}

2)

void example()
{
    lock (mutex)
    {
    //...
    return myData;
    }

}

どれを使えばいいでしょうか?

ベストアンサー1

基本的に、どちらでもコードがシンプルになります。単一の終了ポイントは素晴らしい理想ですが、それを実現するためだけにコードを変形することはしません... また、代替案として、ローカル変数を宣言し (ロックの外側)、それを初期化し (ロックの内側)、それを返す (ロックの外側) 場合、ロック内で単純な "return 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シンプルさを好みますが、どちらにも興奮しません。

おすすめ記事