116 votes

Or contre OrElse

Quelle est la différence entre o y OuElse ?

if temp is dbnull.value or temp = 0

produit l'erreur :

L'opérateur '=' n'est pas défini pour le type 'DBNull' et le type 'Integer'.

alors que celui-ci fonctionne comme un charme ! ?

if temp is dbnull.value OrElse temp = 0

3voto

FrankX Points 157

La réponse de Bert n'est pas très précise. Le '|' ou le '&' sont des opérateurs logiques, en C#, ils sont toujours traités comme des opérateurs binaires, voir le code suivant comme exemple

        static void Main()
        {
            object a = null;
            int b = 3;
            if (a == null | a.ToString() == "sdffd")
            {
                Console.WriteLine("dddd");
            }
            Console.WriteLine(b | b);
            Console.Read();
        }

Le texte suivant est IL

    .method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       62 (0x3e)
  .maxstack  3
  .locals init ([0] object a,
           [1] int32 b,
           [2] bool CS$4$0000)
   IL_0000:  nop
   IL_0001:  ldnull
   IL_0002:  stloc.0
   IL_0003:  ldc.i4.3
   IL_0004:  stloc.1
   IL_0005:  ldloc.0
   IL_0006:  ldnull
   IL_0007:  ceq
   IL_0009:  ldloc.0
   IL_000a:  callvirt   instance string [mscorlib]System.Object::ToString()
   IL_000f:  ldstr      "sdffd"
   IL_0014:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
   IL_0019:  or
   IL_001a:  ldc.i4.0
   IL_001b:  ceq
   IL_001d:  stloc.2
   IL_001e:  ldloc.2
   IL_001f:  brtrue.s   IL_002e
   IL_0021:  nop
   IL_0022:  ldstr      "dddd"
   IL_0027:  call       void [mscorlib]System.Console::WriteLine(string)
   IL_002c:  nop
   IL_002d:  nop
   IL_002e:  ldloc.1
   IL_002f:  ldloc.1
   IL_0030:  or
   IL_0031:  call       void [mscorlib]System.Console::WriteLine(int32)
   IL_0036:  nop
   IL_0037:  call       int32 [mscorlib]System.Console::Read()
   IL_003c:  pop
   IL_003d:  ret
    } // end of method Program::Main

lorsque vous utilisez || pour tester "a == null" et "a.ToString() == "sdffd", l'IL sera

 .method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       63 (0x3f)
  .maxstack  2
  .locals init ([0] object a,
           [1] int32 b,
           [2] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldnull
  IL_0002:  stloc.0
  IL_0003:  ldc.i4.3
  IL_0004:  stloc.1
  IL_0005:  ldloc.0
  IL_0006:  brfalse.s  IL_001d
  IL_0008:  ldloc.0
  IL_0009:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_000e:  ldstr      "sdffd"
  IL_0013:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
  IL_0018:  ldc.i4.0
  IL_0019:  ceq
  IL_001b:  br.s       IL_001e
  IL_001d:  ldc.i4.0
  IL_001e:  stloc.2
  IL_001f:  ldloc.2
  IL_0020:  brtrue.s   IL_002f
  IL_0022:  nop
  IL_0023:  ldstr      "dddd"
  IL_0028:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_002d:  nop
  IL_002e:  nop
  IL_002f:  ldloc.1
  IL_0030:  ldloc.1
  IL_0031:  or
  IL_0032:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0037:  nop
  IL_0038:  call       int32 [mscorlib]System.Console::Read()
  IL_003d:  pop
  IL_003e:  ret
} // end of method Program::Main

Maintenant vous pouvez voir la différence, s'il vous plaît ne pensez pas que le '|' ou 'et' comme opérateur conditionnel, c'est juste un opérateur logique, je ne pense pas qu'il soit nécessaire de l'utiliser pour juger la condition.

1voto

TomXP411 Points 101

La raison pour laquelle la compilation échoue dans l'exemple est que l'ordre des opérations.

L'analyseur d'expression essaie d'évaluer d'abord "dbnull.value or temp".

if temp is (dbnull.value or temp) = 0

L'erreur est ici, parce que vous ne pouvez pas faire un OU bit à bit entre un entier (temp) et dbnull.value.

OrElse résout ce problème, non pas parce qu'il est court-circuité, mais parce qu'il est plus bas dans l'ordre des opérations Ainsi, "temp est dbnull.value" et "3=0" sont évalués en premier, plutôt que l'analyseur syntaxique n'essaie de comparer dbNull et temp.

Donc l'évaluation avec OrElse fonctionne comme vous l'attendez : (suppose que temp=3)

if temp is dbnull.value OrElse temp = 0 then
if 3 is dbnull.value OrElse 3 = 0 then
if false OrElse 3=0 then
if false OrElse false then
if false then

Il s'agissait en fait d'un examen d'entrée dans une société de logiciels pour laquelle je travaillais, et c'était un problème courant que je rencontrais en VB6. C'est donc une bonne idée de mettre entre parenthèses vos sous-expressions lorsque vous utilisez des opérateurs booléens :

Cela aurait compilé correctement :

if (temp is dbnull.value) Or (temp = 0) then 

Bien que, comme tout le monde l'a déjà souligné, OrElse et AndAlso sont vraiment les opérateurs corrects à utiliser dans ce contexte.

0voto

KnowKnot Points 16

À moins que la logique de votre code ne nécessite le comportement de court-circuitage qu'offre OrElse, je pencherais pour l'utilisation de l'opérateur Or car :

  • L'utilisation de "Ou" est simple et nécessite moins de saisie.
  • L'économie de temps de calcul réalisée en utilisant OrElse est négligeable dans la plupart des cas.
  • Plus important encore, l'utilisation d'OrElse peut masquer des erreurs dans les clauses ultérieures qui peuvent ne pas être initialement révélées jusqu'à ce que ces conditions soient finalement satisfaites par la logique du programme.

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