source

오르 대 오르세

lovecheck 2023. 5. 12. 22:21
반응형

오르 대 오르세

오어와 오어 엘즈의 차이점은 무엇입니까?

if temp is dbnull.value or temp = 0

다음 오류가 발생합니다.

'DBNull' 유형과 'Integer' 유형에 대해 연산자 '='이(가) 정의되지 않았습니다.

이것이 매력적으로 작동하는 동안!?

if temp is dbnull.value OrElse temp = 0

OrElse짧은 설명을 제공하는 운영자입니다.Or아닙니다.

부울 'or' 연산자의 정의에 따르면, 첫 번째 항이 참이면 전체가 확실히 참이므로 두 번째 항을 평가할 필요가 없습니다.

OrElse이것을 알고 있기 때문에 평가하려고 하지 않습니다.temp = 0 그것이되면.temp Is DBNull.Value

Or이를 알지 못하며 항상 두 항을 평가하려고 시도합니다.temp Is DBNull.Value0과 비교할 수 없어서 넘어집니다.

당신은...뭐, 어떤 것이 말이 되든.

이것은 C#과 동일한 동작으로, 모든 사람이 Coditional Or(||)와 Conditional And(&&)를 사용하며, Or(|)와 And(&)도 정규입니다.그래서 C#과 VB를 비교합니다.순:

=> 또는

=> 기타

=> 그리고

=> 그리고 또한

조건부 부울 연산자는 생성된 경우 중첩되지 않도록 하는 데 매우 유용합니다.그러나 때때로 두 코드 경로 모두에 도달하기 위해 일반적인 부울 연산자가 필요합니다.

또는 Else는 단락입니다. 즉, 첫 번째 면이 일치하는 경우 식의 한 면만 테스트됩니다.

AndAlso와 마찬가지로 전반부가 실패할 경우 표현식의 한쪽만 테스트합니다.

또는 첫 번째 식을 평가한 다음 참이면 OR이 두 식을 평가한 후 해당 식을 평가합니다.

예:

Textbox1.Text= 4

Textbox2.Text= ""

OrEse 사용

  If TextBox1.Text > 2 OrElse TextBox2.Text > 3 Then
      MsgBox("True")
  End If

결과: TRUE


OR 사용

 If TextBox1.Text > 2 Or TextBox2.Text > 3 Then

            MsgBox("True")
  End If

결과: 오류가 문자열을 이중으로 변환할 수 없습니다.

(다른 답변을 보고 제가 심하게 틀렸다는 것을 깨달았습니다.)

OrElse 연산자는 "두 개의 표현식에 대해 단락 논리적 분리를 수행한다." 즉, 왼쪽 피연산자가 참이고 따라서 전체 표현식이 참임이 보장되면 오른쪽 피연산자도 평가되지 않을 것입니다(이것은 다음과 같은 경우에 유용합니다).

string a;
//...
if (a is null) or (a = "Hi") //...

오른쪽 피연산자가 NullReferenceException을 던지지 않도록 합니다.

저는 이것(느린 평가)이 기본 행동이 아니라는 것에 진심으로 놀랐습니다.or그리고.andC/C++와 C# (그리고 다른 많은 언어들...)로 된 것처럼.

버트의 대답은 정확하지 않습니다.'|' 또는 '&'은 논리 연산자이며, C#에서는 항상 비트 연산자로 취급됩니다. 다음 코드를 예로 참조하십시오.

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

다음은 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

||을 사용하여 "a == null" 및 "a"를 테스트하는 경우.ToString() == "sdffd"에 대해 IL은

 .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

이제 차이를 알 수 있습니다. '|' 또는 '그리고'를 조건 연산자로 생각하지 마십시오. 논리 연산자일 뿐이므로 조건을 판단하는 데 사용할 필요는 없다고 생각합니다.

이 예제에서 컴파일이 실패하는 이유는 작업 순서 때문입니다.

식 구문 분석기가 먼저 "dbnull.value 또는 temp"를 평가하려고 합니다.

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

정수(temp)와 dbnull.value 사이에서 비트 OR을 수행할 수 없기 때문에 오류가 발생합니다.

또는 Else가 이 문제를 해결하는 것은 단락이 아니라 작업 순서가 낮기 때문입니다. 따라서 파서가 dbNull과 temp를 비교하려고 하는 것이 아니라 "dbnull.value가 dbnull입니다."와 "3=0"이 먼저 평가되고 있습니다.

따라서 OrElse를 사용한 평가는 예상대로 작동합니다. (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

이것은 사실 제가 일하던 소프트웨어 회사의 입사 시험에서 VB6에서 흔히 마주치곤 했던 문제였습니다.따라서 부울 연산자를 사용할 때는 하위 표현식을 괄호로 묶는 것이 좋습니다.

이것은 올바르게 컴파일되었을 것입니다.

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

하지만, 모두가 이미 지적했듯이, OrElse와 AndAlso는 이러한 맥락에서 사용하기에 정말로 올바른 연산자입니다.

코드 로직이 OrElse가 제공하는 단락 동작을 요구하지 않는 한, 저는 다음과 같은 이유로 Or 연산자를 사용하는 쪽으로 기울 것입니다.

  • "Or"을 사용하는 것은 간단하고 타이핑이 덜 필요합니다.
  • 대부분의 경우 OrElse를 사용할 때의 계산 시간 절약은 무시할 수 있습니다.
  • 가장 중요한 것은 OrElse를 사용하면 나중에 해당 조건이 최종적으로 프로그램 논리에 의해 충족될 때까지 처음에 드러나지 않을 수 있는 오류를 숨길 수 있다는 것입니다.

언급URL : https://stackoverflow.com/questions/1170754/or-versus-orelse

반응형