2010-09-04 13 views

Trả lời

29

Đáng ngạc nhiên, khi bạn thực hiện các phép tính trên byte, việc tính toán sẽ được thực hiện bằng cách sử dụng các giá trị int, với các byte ngầm được đúc thành (int) trước tiên. Điều này cũng đúng với short s và tương tự float s được chuyển đổi thành double khi thực hiện số học dấu phẩy động.

Đoạn thứ hai là tương đương với:

byte someVar; 
someVar = (int) someVar - 3; 

Bởi vì điều này bạn phải đúc kết quả trở lại (byte) để có được trình biên dịch để chấp nhận sự phân công.

someVar = (byte) (someVar - 3); 
+0

Ai đó có thể xác minh xem loại truyền xảy ra ở cấp IL trong someVar- = 3 hay không; thí dụ? Nó có tạo ra cùng mã IL không? – Dested

+2

Tôi vừa kiểm tra với Reflector. Toán tử '- =' tạo ra một 'conv.u1' ở mức IL, đó là lý do tại sao đoạn đầu tiên làm việc –

+5

@Dested Các quy tắc chính xác được đưa ra trong Đặc tả Ngôn ngữ C#. Nó nói rõ: _ "Nguyên tắc thứ hai ở trên cho phép' x op = y' được đánh giá là 'x = (T) (x op y)' trong các ngữ cảnh nhất định. khi toán hạng bên trái có kiểu 'sbyte',' byte', 'short',' ushort' hoặc 'char'. Ngay cả khi cả hai đối số đều thuộc một trong các loại đó, toán tử được xác định trước tạo ra kết quả của kiểu' int' Như được mô tả trong §7.3.6.2, do đó, không có dàn diễn viên sẽ không thể gán kết quả cho toán hạng bên trái. "_ –

11

Dưới đây là một bản sao của một bảng trong đặc tả CLI (ECMA 335) mà xác định đó toán hạng có giá trị trên các nhà khai thác số nhị phân của các loại A op B, trong đó A và B là các toán hạng và "op" là các nhà điều hành, như Opcodes.Sub mà bạn đang sử dụng trong đoạn mã của bạn:

alt text

Một số chú thích được yêu cầu với điều này:

  • "int mẹ đẻ" là IntPtr trong một chương trình C#
  • F đại diện cho một loại dấu chấm động, tăng gấp đôi hoặc trôi nổi trong C#
  • & đại diện cho một giá trị con trỏ, các hộp được tô bởi vì họ là những hoạt động không an toàn
  • O đại diện cho một tham chiếu đối tượng
  • x là một hoạt động không được phép.

Lưu ý hàng và cột cho F, cả hai toán hạng phải là dấu phẩy động, bạn không thể trực tiếp thêm, giả sử int tăng gấp đôi. Trình biên dịch C# đối phó với giới hạn đó bằng cách tự động chuyển đổi toán hạng int thành gấp đôi để toán tử hợp lệ.

Có liên quan đến câu hỏi của bạn: cũng lưu ý rằng các loại byte, sbyte, char, ngắn và ushort không có mặt. Cách tiếp cận tương tự, trình biên dịch chuyển đổi các toán hạng thành kiểu nhỏ nhất có thể biểu diễn giá trị để toán tử có thể được sử dụng. Mà sẽ là int32. Theo bảng, kết quả của hoạt động sẽ là int32.

Bây giờ đây là chà: kết quả là int32 nhưng gán lại giá trị byte yêu cầu một chuyển đổi thu hẹp. Từ 32 bit đến 8 bit. Đó là rắc rối bởi vì nó mất đi các bit quan trọng. Trình biên dịch C# yêu cầu bạn làm rõ điều đó. Bạn về cơ bản thừa nhận rằng bạn biết những gì bạn đang làm và bạn nhận thức được kết quả có khả năng gây ngạc nhiên.Như thế này:

byte v = 255; 
v = (byte)(v + 1); 

Toán tử - = là một vấn đề vì không có cách hiệu quả để áp dụng yêu cầu. Nó không thể hiện rõ trong cú pháp ngôn ngữ. Sử dụng (byte) 3 không có ý nghĩa, các chữ được chuyển đổi sang int32 anyway để làm cho các nhà điều hành làm việc.

Họ punted vấn đề, trình biên dịch tự động phát ra các diễn viên mà không cần sự giúp đỡ của bạn.

+0

điều này giải thích tại sao tôi không thể sử dụng sự phản chiếu để ẩn hoàn toàn giữa các loại. – fusi