172 votes

Une instruction return soient à l’intérieur ou à l’extérieur une serrure ?

Je viens de réaliser que dans un certain endroit dans mon code, j’ai l’instruction de retour à l’intérieur de la serrure et parfois à l’extérieur. Quel est le meilleur ?

1)

2)

Lequel dois-je utiliser ?

224voto

Marc Gravell Points 482669

Essentiellement, qui jamais rend le code plus simple. Seul point de sortie est un bel idéal, mais je ne pliez pas le code de la forme, juste pour y parvenir... Et si l'alternative est de déclarer une variable locale (à l'extérieur de la serrure), l'initialisation (à l'intérieur de la serrure) et ensuite de le retourner (à l'extérieur de la serrure), alors je dirais qu'un simple "retour foo" à l'intérieur de la serrure est beaucoup plus simple.

Pour montrer la différence de l'IL, permet de code:

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;
    }
}

(notez que je serais heureux de soutenir que ReturnInside est plus simple/nettoyeur peu de C#)

Et regardez le IL (mode release, etc):

.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
}

Donc, au niveau IL qu'ils sont [donner ou prendre quelques noms] identique (j'ai appris quelque chose ;-p). En tant que tel, la seule raisonnable de comparaison est le (très subjective) de la loi de codage local style... je préfère ReturnInside de la simplicité, mais je n'arrive pas à être excité à propos.

47voto

Greg Beech Points 55270

Il ne fait aucune différence ; ils sont tous deux traduits à la même chose par le compilateur.

Pour clarifier, soit se traduit effectivement à quelque chose avec la sémantique suivante :

37voto

Ricardo Villamil Points 3080

Je mettrais sans aucun doute le retour à l’intérieur de la serrure. Sinon, vous risquez un autre thread entrant dans la serrure et modifiez votre variable avant le retour statemet, rendant ainsi l’appelant d’origine reçoivent une valeur différente de celle attendue.

5voto

Rob Walker Points 25840

Si penser la serrure à l’extérieur est plus beau, mais soyez prudent si vous finissez par modifier le code pour :

Si f() doit être appelé avec le verrou détenu puis il doit évidemment être à l’intérieur de la serrure, gardant ainsi retourne à l’intérieur de la serrure par souci de cohérence logique.

5voto

Edward Kmett Points 18369

Ça dépend,

Je vais aller à contre courant ici. En général, je serait de retour à l'intérieur de la serrure.

Habituellement, la variable mydata est une variable locale. Je suis fan de déclarer des variables locales alors que je les initialiser. J'ai rarement des données pour initialiser ma valeur de retour de l'extérieur de ma serrure.

Donc votre comparaison est en fait erronée. Alors que, idéalement, la différence entre les deux options que vous aviez écrit, qui semble donner le feu vert pour le cas 1, dans la pratique, il est un peu plus laide.

void example() { 
    int myData;
    lock (foo) { 
        myData = ...;
    }
    return myData
}

vs

void example() { 
    lock (foo) {
        return ...;
    }
}

- Je trouver des cas 2 à être beaucoup plus facile à lire et plus difficile à vis en place, en particulier pour les courts extraits.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X