13

Sử dụng Casting null doesn't compile là nguồn cảm hứng, và từ bình luận Eric Lippert của:Tại sao chuyển đổi tiềm ẩn này từ int thành công việc?

Đó chứng tỏ một trường hợp thú vị. "uint x = (int) 0;" sẽ thành công ngay cả khi int không chuyển đổi hoàn toàn thành uint.

Chúng tôi biết điều này không làm việc, vì object không thể được gán cho string:

string x = (object)null; 

Nhưng điều này không, mặc dù trực giác nó không nên:

uint x = (int)0; 

Tại sao không trình biên dịch cho phép trường hợp này, khi int không được chuyển đổi hoàn toàn thành uint?

+1

Tôi cho rằng cùng một lý do 'đơn vị x = 0' hoạt động. '0' là một int đã ký trừ khi bạn chỉ định' unit x = 0U'. – vcsjones

+6

Có thể là 6.1.9 của spec và chiết khấu của int int, bởi vì 0 đã là một int. Trong khi thường một int không chuyển đổi hoàn toàn thành uint (6.1.2), một biểu thức * liên tục * của kiểu int có thể được chuyển đổi. –

+0

Giá trị nào '0' ngầm có vẻ như là một biểu thức liên tục?Liệu trình biên dịch có bỏ qua '' int ''và sử dụng' 0' làm hằng số 'uint' không? – Yuck

Trả lời

26

Chuyển đổi hằng số nguyên được xử lý rất đặc biệt bằng ngôn ngữ C#; đây là phần 6.1.9 của đặc điểm kỹ thuật:

Biểu thức liên tục của loại int có thể được chuyển đổi thành loại sbyte, byte, short, ushort, uint hoặc ulong, với giá trị của biểu thức không đổi nằm trong phạm vi của loại đích. Một biểu thức liên tục của loại dài có thể được chuyển đổi thành loại ulong, miễn là giá trị của biểu thức hằng số không âm.

này cho phép bạn làm những việc như:

byte x = 64; 

mà nếu không sẽ đòi hỏi một chuyển đổi rõ ràng xấu xí:

byte x = (byte)64; // gross 
+12

+1 Rất tuyệt. Tôi đã đi với '// yuck', mặc dù;) – Yuck

+0

Vì vậy, trong trường hợp của' uint i = (int) 0; ', trình biên dịch chỉ bỏ qua các diễn viên? Hay chỉ là kết quả của việc đúc một biểu thức không đổi là chính nó là một biểu thức không đổi? – dlev

+3

@dlev: Sau này. Việc đúc một biểu thức liên tục của kiểu int thành int vẫn là một biểu thức không đổi. –

9

Các mã sau wil thất bại với thông báo "Can not ngầm chuyển đổi loại 'int' thành 'uint'. Một chuyển đổi rõ ràng tồn tại (là bạn thiếu một dàn diễn viên?)"

int y = 0; 
uint x = (int)y; 

Và điều này sẽ thất bại với : "giá trị liên tục '-1' không thể được chuyển đổi sang một 'uint"

uint x = (int)-1; 

vì vậy, lý do duy nhất uint x = (int)0; công trình là bởi vì trình biên dịch thấy rằng 0 (hoặc bất kỳ giá trị khác> 0) là một hằng số thời gian biên dịch có thể được chuyển đổi thành uint

+0

Vì vậy, về cơ bản nó tối ưu hóa các diễn viên đi vì nó không cần thiết cho một chữ? – BoltClock

+3

@BoltClock Một biểu thức liên tục có thể được chuyển đổi tại thời gian biên dịch để dàn diễn viên thực sự bị loại bỏ. –

2

Trong trình biên dịch chung có 4 bước, trong đó các mã được chuyển đổi. Văn bản được mã hóa> Mã được phân tích cú pháp> Một AST được tạo + liên kết> AST được chuyển đổi sang ngôn ngữ đích.

Việc đánh giá các hằng số như số và chuỗi xảy ra dưới dạng bước đầu tiên và trình biên dịch có thể xử lý 0 dưới dạng mã thông báo hợp lệ và bỏ qua quá trình truyền.