짧은 답변:
IL에는 "같지 않은 비교"명령 !=
이 없으므로 C # 연산자는 정확히 일치하지 않으며 문자 그대로 번역 할 수 없습니다.
그러나 "비교-동일"명령 ( 연산자 ceq
와 직접 대응 ==
)이 있으므로 일반적으로 x != y
약간 더 긴 것으로 번역 (x == y) == false
됩니다.
이 또한 는 "비교 -보다 큼"IL (의 명령 cgt
) 컴파일러가 널 (null)에 대한 객체의 불평등 비교되는 (즉, 짧은 IL 코드를 생성)를 특정 단축키를 활용할 수 있습니다, obj != null
그들은 것처럼, "번역 취득 obj > null
".
좀 더 자세히 살펴 보겠습니다.
IL에 "같지 않은 비교"명령이 없으면 컴파일러가 다음 방법을 어떻게 변환합니까?
static bool IsNotEqual(int x, int y)
{
return x != y;
}
위에서 이미 언급했듯이 컴파일러는 다음으로 x != y
바꿉니다 (x == y) == false
.
.method private hidebysig static bool IsNotEqual(int32 x, int32 y) cil managed
{
ldarg.0 // x
ldarg.1 // y
ceq
ldc.i4.0 // false
ceq // (note: two comparisons in total)
ret
}
컴파일러가 항상 상당히 오래 걸리는 패턴을 생성하는 것은 아닙니다. y
상수 0으로 바꾸면 어떻게되는지 보자 :
static bool IsNotZero(int x)
{
return x != 0;
}
생성 된 IL은 일반적인 경우보다 다소 짧습니다.
.method private hidebysig static bool IsNotZero(int32 x) cil managed
{
ldarg.0 // x
ldc.i4.0 // 0
cgt.un // (note: just one comparison)
ret
}
컴파일러는 부호있는 정수가 2의 보수 (결과 비트 패턴이 부호없는 정수로 해석되는 경우- .un
평균-0이 가능한 최소값을 갖는 경우)에 저장된다는 사실을 이용할 수 있으므로 x == 0
마치 마치 unchecked((uint)x) > 0
.
컴파일러는 불평등 검사에 대해 동일한 작업을 수행 할 수 있습니다 null
.
static bool IsNotNull(object obj)
{
return obj != null;
}
컴파일러는 다음과 거의 동일한 IL을 생성합니다 IsNotZero
.
.method private hidebysig static bool IsNotNull(object obj) cil managed
{
ldarg.0
ldnull // (note: this is the only difference)
cgt.un
ret
}
분명히, 컴파일러는 null
참조의 비트 패턴이 모든 객체 참조에 가능한 가장 작은 비트 패턴 이라고 가정 할 수 있습니다.
이 바로 가기는 공통 언어 인프라 주석 표준 (2003 년 10 월 1 판) (491 페이지의 표 6-4, "이진 비교 또는 분기 작업"의 각주 )에 명시 적으로 언급되어 있습니다 .
" cgt.un
는 ObjectRefs (O)에서 허용되고 검증 가능합니다. 이것은 ObjectRef를 null과 비교할 때 일반적으로 사용됩니다 ("같지 않은 비교 "명령이없는 경우가 더 분명합니다)."
int
범위의 음수가 아닌 값 이와 동일한 방식으로 표시되는 방식int
으로 저장됩니다uint
. 그것은 2의 보수보다 훨씬 약한 요구 사항입니다.