2008-09-15 29 views
5

Tôi đang sử dụng int làm ví dụ, nhưng điều này áp dụng cho bất kỳ loại giá trị trong Net.Net 2+: tại sao nếu (1 == null) không còn ném ngoại lệ trình biên dịch?

Trong Net 1 sau đây sẽ ném một trình biên dịch ngoại lệ:

int i = SomeFunctionThatReturnsInt(); 

if(i == null) //compiler exception here 

Bây giờ (trong Net 2 hoặc 3.5) ngoại lệ đó đã biến mất.

Tôi biết tại sao điều này là:

int? j = null; //nullable int 

if(i == j) //this shouldn't throw an exception 

Vấn đề là bây giờ bởi vì int? là nullable và int có một diễn viên tiềm ẩn để int?. Cú pháp trên là ma thuật trình biên dịch. Thực sự chúng tôi đang thực hiện:

Nullable<int> j = null; //nullable int 

//compiler is smart enough to do this 
if((Nullable<int>) i == j) 

//and not this 
if(i == (int) j) 

Vì vậy, bây giờ, khi chúng ta làm i == null chúng tôi nhận được:

if((Nullable<int>) i == null) 

Cho rằng C# đang làm biên dịch logic để tính toán này anyway lý do tại sao nó không thể là thông minh đủ để không làm điều đó khi giao dịch với các giá trị tuyệt đối như null?

Trả lời

3

Tôi không nghĩ đây là sự cố biên dịch mỗi giây; giá trị số nguyên không bao giờ là rỗng, nhưng ý tưởng đánh đồng chúng không hợp lệ; đó là hàm hợp lệ luôn trả về false. Và trình biên dịch biết; mã

bool oneIsNull = 1 == null; 

biên dịch, nhưng đưa ra cảnh báo trình biên dịch: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type '<null>'. Vì vậy nếu bạn muốn lỗi trình biên dịch trở lại, hãy vào các thuộc tính của dự án và bật 'xử lý cảnh báo là lỗi' cho lỗi này, và bạn sẽ bắt đầu thấy chúng như là các vấn đề phá vỡ xây dựng một lần nữa. Quay lại đầu trang Cung cấp Phản hồi GIẢI PHÁP

1

Trình biên dịch vẫn tạo cảnh báo khi bạn so sánh loại không có giá trị null với giá trị rỗng, đó chỉ là cách mà nó cần. Có thể mức độ cảnh báo của bạn quá thấp hoặc điều này đã được thay đổi trong các phiên bản gần đây (tôi chỉ thực hiện điều đó trong .net 3.5).

3

Odd ... biên soạn này với VS2008, nhắm mục tiêu NET 3.5:

static int F() 
    { 
     return 42; 
    } 

    static void Main(string[] args) 
    { 
     int i = F(); 

     if (i == null) 
     { 
     } 
    } 

tôi nhận được một trình biên dịch cảnh báo

warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' 

Và nó tạo ra IL sau ... mà có lẽ các JIT sẽ tối ưu hóa

L_0001: call int32 ConsoleApplication1.Program::F() 
    L_0006: stloc.0 
    L_0007: ldc.i4.0 
    L_0008: ldc.i4.0 
    L_0009: ceq 
    L_000b: stloc.1 
    L_000c: br.s L_000e 

Bạn có thể đăng đoạn mã không?

+0

Trình biên dịch chính xác phát hiện ra rằng nó không bao giờ đúng, giống như khi bạn đã thực hiện 1 == 2. Đó là đủ thông minh để biết rằng int có thể được ngầm đúc đến int? và đó int? có thể được so sánh với null. Tôi nghi ngờ đủ thông minh của người tối ưu hóa để loại bỏ toàn bộ khối. – Keith

0

Cảnh báo mới (3.5 Tôi nghĩ) - lỗi giống như nếu tôi đã thực hiện 1 == 2, thông minh đủ để phát hiện không bao giờ đúng.

Tôi nghi ngờ rằng với đầy đủ 3,5 tối ưu hóa toàn bộ tuyên bố sẽ chỉ bị tước bỏ, vì nó khá thông minh với không bao giờ đánh giá đúng sự thật.

Mặc dù tôi có thể muốn 1==2 để biên dịch (để tắt một khối chức năng trong khi tôi thử nghiệm một ví dụ khác chẳng hạn) Tôi không muốn 1==null.

0

Nó phải là một lỗi biên dịch-thời gian, bởi vì các loại không tương thích (loại giá trị không bao giờ có thể null). Thật buồn khi không phải vậy.

+0

Đọc toàn bộ câu hỏi, tôi giải thích lý do tại sao nó xảy ra. Câu hỏi đặt ra là tại sao nó không thể được coi là một trường hợp đặc biệt. – Keith

+0

Khi tôi nói "ought" tôi có nghĩa là có một mệnh lệnh đạo đức, không phải đó là những gì tôi mong đợi trình biên dịch để làm. Lý do bạn mô tả không phải là ít hấp dẫn nhất; họ nên làm cho một thất bại biên dịch tĩnh này. – DrPizza

1

Khung 2.0 giới thiệu loại giá trị có thể vô hiệu. Mặc dù hằng số chữ "1" không bao giờ có thể là null, kiểu cơ bản của nó (int) bây giờ có thể được chuyển thành kiểu int không có khả năng. Tôi đoán là trình biên dịch không còn có thể giả định rằng các kiểu int không phải là nullable, ngay cả khi nó là một hằng số theo nghĩa đen. Tôi nhận được cảnh báo khi biên soạn 2.0:

Cảnh báo 1 Kết quả của biểu thức luôn là 'false' vì giá trị của loại 'int' không bao giờ bằng 'null' của loại 'int?'

+0

Giống như tôi đã nói - trình biên dịch biết rằng int có thể được ngầm đúc đến int? và int? có thể được so sánh với null. Cảnh báo là một cảnh báo chung cho bất kỳ so sánh không đúng sự thật nào. 1 == 2 sẽ ném cùng một cảnh báo. – Keith

Các vấn đề liên quan