Câu trả lời đơn giản và chính xác là "vì đặc tả ngôn ngữ C# nói như vậy".
Rõ ràng bạn không hài lòng với câu trả lời đó và muốn biết "tại sao nó lại nói như vậy". Bạn đang tìm kiếm "nguồn đáng tin cậy và/hoặc chính thức", điều đó sẽ hơi khó khăn. Những quyết định thiết kế này đã được thực hiện từ lâu, 13 năm là rất nhiều con chó sống trong kỹ nghệ phần mềm. Chúng được tạo ra bởi những "bộ đếm thời gian cũ" như Eric Lippert gọi chúng, chúng đã chuyển sang những thứ lớn hơn và tốt hơn và không đăng câu trả lời ở đây để cung cấp một nguồn chính thức.
Tuy nhiên, có thể suy ra, có nguy cơ chỉ đáng tin cậy. Bất kỳ trình biên dịch được quản lý nào, như C#, có ràng buộc rằng nó cần tạo mã cho máy ảo .NET. Các quy tắc được cẩn thận (và khá dễ đọc) được mô tả trong thông số CLI. Đây là thông số kỹ thuật Ecma-335, bạn có thể tải xuống miễn phí from here.
Chuyển sang phân vùng III, chương 3.1 và 3.2. Chúng mô tả hai hướng dẫn IL có sẵn để thực hiện thêm, add
và add.ovf
. Nhấp vào liên kết đến Bảng 2, "Hoạt động số nhị phân", nó mô tả toán hạng nào được phép cho các lệnh IL đó. Lưu ý rằng chỉ có một vài loại được liệt kê ở đó. byte và ngắn cũng như tất cả các loại unsigned bị thiếu. Chỉ int, dài, IntPtr và dấu phẩy động (float và double) được cho phép. Với các ràng buộc bổ sung được đánh dấu bằng một x, bạn không thể thêm một int vào một ví dụ dài.Những ràng buộc này không hoàn toàn giả tạo, chúng dựa trên những thứ bạn có thể làm hiệu quả hợp lý trên phần cứng có sẵn.
Bất kỳ trình biên dịch được quản lý nào cũng phải giải quyết vấn đề này để tạo ra IL hợp lệ. Điều đó không khó, chỉ cần chuyển đổi ushort thành một loại giá trị lớn hơn trong bảng, một chuyển đổi luôn hợp lệ. Trình biên dịch C# chọn int, loại lớn hơn tiếp theo xuất hiện trong bảng. Hoặc nói chung, chuyển đổi bất kỳ toán hạng nào sang loại giá trị lớn nhất tiếp theo để cả hai đều có cùng loại và đáp ứng các ràng buộc trong bảng.
Tuy nhiên, có một vấn đề mới, một vấn đề khiến các lập trình viên C# khá hấp dẫn. Kết quả của việc bổ sung là loại được quảng cáo. Trong trường hợp của bạn sẽ là int. Vì vậy, thêm hai giá trị ushort của, nói, 0x9000 và 0x9000 có một kết quả int hoàn toàn hợp lệ: 0x12000. Vấn đề là: đó là một giá trị không phù hợp với một nhóm. Giá trị bị tràn. Nhưng nó đã không tràn trong tính toán IL, nó chỉ tràn khi trình biên dịch cố gắng nhồi nhét nó trở lại vào một ushort. 0x12000 bị cắt ngắn thành 0x2000. Một giá trị khác nhau đáng lo ngại chỉ có ý nghĩa khi bạn đếm bằng 2 hoặc 16 ngón tay, không phải với 10.
Đáng chú ý là lệnh add.ovf không giải quyết được vấn đề này. Đây là hướng dẫn sử dụng để tự động tạo ra một ngoại lệ tràn. Nhưng nó không, tính toán thực tế trên ints chuyển đổi đã không tràn.
Đây là nơi đưa ra quyết định thiết kế thực tế. Các bộ định thời cũ dường như đã quyết định rằng chỉ cần cắt ngắn kết quả int để ushort là một nhà máy lỗi. Nó chắc chắn là. Họ quyết định rằng bạn phải thừa nhận rằng bạn biết rằng việc bổ sung có thể tràn và rằng điều đó sẽ ổn nếu điều đó xảy ra. Họ đã làm cho nó vấn đề của bạn, chủ yếu là vì họ không biết làm thế nào để làm cho nó của họ và vẫn tạo ra mã hiệu quả. Bạn phải bỏ. Vâng, điều đó thật đáng buồn, tôi chắc rằng bạn cũng không muốn vấn đề đó.
Khá đáng chú ý là các nhà thiết kế VB.NET đã đưa ra giải pháp khác cho vấn đề. Họ thực sự đã làm cho nó vấn đề của họ và không vượt qua buck. Bạn có thể thêm hai UShort và gán nó cho một UShort mà không có một diễn viên. Sự khác biệt là trình biên dịch VB.NET thực sự tạo ra thêm IL để kiểm tra tình trạng tràn. Đó không phải là mã rẻ, làm cho mỗi lần bổ sung ngắn khoảng 3 lần chậm. Nhưng nếu không, lý do giải thích tại sao Microsoft duy trì hai ngôn ngữ có khả năng tương tự khác.
Ngắn câu chuyện: bạn đang trả giá vì bạn sử dụng loại không phù hợp với kiến trúc cpu hiện đại. Mà chính nó là một lý do thực sự tốt để sử dụng uint thay vì ushort. Nhận được lực kéo ra khỏi ushort là khó khăn, bạn sẽ cần rất nhiều người trong số họ trước khi chi phí của thao tác chúng ra trọng lượng tiết kiệm bộ nhớ. Không chỉ vì thông số CLI giới hạn, lõi x86 mất thêm một chu kỳ CPU để tải một giá trị 16 bit vì byte tiền tố toán hạng trong mã máy. Không thực sự chắc chắn nếu đó vẫn là trường hợp ngày hôm nay, nó được sử dụng để trở lại khi tôi vẫn chú ý đến các chu kỳ đếm. Một con chó năm trước.
Lưu ý rằng bạn có thể cảm thấy tốt hơn về các trình biên dịch xấu xí và nguy hiểm này bằng cách tạo trình biên dịch VB.NET tạo. Vì vậy, bạn nhận được một OverflowException khi diễn viên hóa ra là không khôn ngoan. Sử dụng Project> Properties> Build tab> Advanced button> đánh dấu vào hộp kiểm "Check for overflow/underflow number". Chỉ dành cho bản dựng Gỡ lỗi. Tại sao hộp kiểm này không được tự động bật bởi mẫu dự án là một câu hỏi rất băn khoăn khác, một quyết định đã được thực hiện cách đây quá lâu.
http://bytes.com/topic/c-sharp/answers/256857-does-ushort-ushort-return-int-value (xem câu trả lời J.Skeets) –
Tôi đã cập nhật câu trả lời của mình từ thông số kỹ thuật C# từ microsoft – Habib