Câu trả lời ngắn:
Không có hướng dẫn "so sánh không bằng" trong IL, vì vậy !=toán tử C # không có sự tương ứng chính xác và không thể được dịch theo nghĩa đen.
Tuy nhiên, có một lệnh "so sánh bằng" ( ceq, tương ứng trực tiếp với ==toán tử), vì vậy trong trường hợp chung, x != yđược dịch giống như tương đương dài hơn một chút (x == y) == false.
Ngoài ra còn có một lệnh "so sánh lớn hơn" trong IL ( cgt) cho phép trình biên dịch thực hiện một số phím tắt nhất định (nghĩa là tạo mã IL ngắn hơn), một trong số đó là so sánh bất bình đẳng của các đối tượng với null obj != null, được dịch như thể chúng là " obj > null".
Chúng ta hãy đi vào chi tiết hơn.
Nếu không có lệnh "so sánh không bằng" trong IL, thì phương thức sau đây sẽ được dịch bởi trình biên dịch như thế nào?
static bool IsNotEqual(int x, int y)
{
return x != y;
}
Như đã nói ở trên, trình biên dịch sẽ biến x != ythành (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
}
Nó chỉ ra rằng trình biên dịch không phải lúc nào cũng tạo ra mô hình khá dài này. Hãy xem điều gì xảy ra khi chúng ta thay thế ybằng hằng số 0:
static bool IsNotZero(int x)
{
return x != 0;
}
IL được sản xuất có phần ngắn hơn so với trường hợp chung:
.method private hidebysig static bool IsNotZero(int32 x) cil managed
{
ldarg.0 // x
ldc.i4.0 // 0
cgt.un // (note: just one comparison)
ret
}
Trình biên dịch có thể lợi dụng thực tế là các số nguyên đã ký được lưu trữ trong phần bù hai (trong đó, nếu các mẫu bit kết quả được hiểu là các số nguyên không dấu - đó là những gì .uncó nghĩa là - 0 có giá trị nhỏ nhất có thể), vì vậy nó dịch x == 0như thể nó là unchecked((uint)x) > 0.
Hóa ra trình biên dịch có thể làm tương tự đối với kiểm tra bất đẳng thức đối với null:
static bool IsNotNull(object obj)
{
return obj != null;
}
Trình biên dịch tạo ra gần như cùng IL với IsNotZero:
.method private hidebysig static bool IsNotNull(object obj) cil managed
{
ldarg.0
ldnull // (note: this is the only difference)
cgt.un
ret
}
Rõ ràng, trình biên dịch được phép giả định rằng mẫu bit của nulltham chiếu là mẫu bit nhỏ nhất có thể cho bất kỳ tham chiếu đối tượng nào.
Phím tắt này được đề cập rõ ràng trong Tiêu chuẩn cơ sở hạ tầng ngôn ngữ chung (phiên bản 1 từ tháng 10 năm 2003) (trên trang 491, như một chú thích của Bảng 6-4, "So sánh nhị phân hoặc Hoạt động chi nhánh"):
" cgt.unđược cho phép và có thể kiểm chứng trên ObjectRefs (O). Điều này thường được sử dụng khi so sánh ObjectRef với null (không có hướng dẫn" so sánh không bằng ", nếu không sẽ là một giải pháp rõ ràng hơn)."
intphạm vi có cùng biểu diễnintgiống như khi chúng thực hiệnuint. Đó là một yêu cầu yếu hơn nhiều so với bổ sung của hai.