2008-10-26 28 views
12

Khi bạn cố gắng khai báo biến không dấu trong C# .NET với giá trị nằm ngoài phạm vi giá trị, nó được gắn cờ là lỗi trình biên dịch, nhưng nếu bạn tạo ra giá trị âm khi chạy và gán giá trị đó biến trong thời gian chạy giá trị kết thúc tốt đẹp.Sự khác nhau của hai 'uint'

uint z = -1; // Will not compile 

uint a = 5; 
uint b = 6; 
uint c = a - b; // Will result in uint.MaxValue 

Có lý do chính đáng khiến các biến không được ký bọc trong trường hợp này thay vì ném ngoại lệ?

Cảm ơn.

+0

Tương tự giữ cho ulong – Llyle

Trả lời

26

Khai báo biến chưa được gán trong C# không được gắn cờ với lỗi - cố gán giá trị không hợp lệ cho biến là. Ví dụ: đây là một biến không chắc chắn được gán (giả định là biến địa phương) sau khi khai báo:

uint z; 

-1 không phải là giá trị hợp lệ cho một số tiền lớn hơn 0,5, đó là lý do tại sao ví dụ của bạn sẽ không biên dịch.

Bây giờ, phần còn lại: các loại số nguyên chỉ bị tràn khi tràn - giống như việc thêm 1 đến int.MaxValue trả lại int.MinValue. Đây là một cải tiến hiệu suất đáng kể so với việc có chương trình kiểm tra từng hoạt động cho tràn - với chi phí có khả năng không phát hiện lỗi.

Chỉ khi bạn đang ở trong một bối cảnh không được kiểm soát, hãy nhớ bạn - nếu bạn thực hiện bất kỳ thao tác nào trong các thao tác này trong ngữ cảnh được chọn, bạn sẽ nhận được một ngoại lệ. Ví dụ;

class Test 
{ 
    static void Main() 
    { 
     checked 
     { 
      uint a = 5; 
      uint b = 6; 
      uint c = a - b; 
     } 
    } 
} 

Chạy điều đó và bạn sẽ thấy số OverflowException bị ném. Nếu đó là những gì bạn muốn cho toàn bộ dự án của mình, bạn có thể đặt nó trong thuộc tính dự án (hoặc biên dịch với tùy chọn dòng lệnh /checked+ để csc.)

EDIT: Cần lưu ý rằng các câu trả lời khác đã cho thấy rằng bạn có thể đặt số lượng mã nhỏ hơn trong ngữ cảnh đã chọn - chỉ cần khai báo và gán c hoặc thậm chí chỉ là phép tính. Đó là tất cả khá linh hoạt.

+0

Darm - pipped to it ... Tôi nhấn "Post" để tìm thấy bạn đã có +5 ... [delete ...] –

+0

Đó là một tập hợp phiếu bầu nhanh chóng. Nó không giống như nó được ngồi xung quanh trong một thời gian ... –

+1

Đáng ngạc nhiên là tôi chưa bao giờ gặp phải các ngữ cảnh được chọn và không được kiểm tra. Điều đó thật tuyệt. – Llyle

7

Gói là do không được đánh dấu chọn. Nếu bạn thêm khối "đã chọn", thì phát hiện tràn sẽ:

uint a = 3, b = 4; 
    checked 
    { 
     uint c = a - b; // throws an overflow 
    } 

Đối với trình biên dịch: nó chỉ yêu cầu dữ liệu hợp lệ.

+0

Tôi đã quen với môi trường được kiểm tra, vì vậy hãy xem MSDN và trạng thái này được chọn là mặc định? - http://msdn.microsoft.com/en-us/library/74b4xzyw(VS.85).aspx – MattH

3

Đây chỉ là mặc định - bạn có thể thay đổi cài đặt biên dịch để bật kiểm tra tràn bộ đếm thời gian chạy. Nếu bạn bật tính năng này, các ngoại lệ sẽ được ném như bạn mong đợi. Ngoài ra, bạn có thể bật kiểm tra cho một hoạt động cụ thể bằng cách đặt nó bên trong một khối đã chọn.

uint c = checked(a - b); 
0

Có lẽ giá trị làm rõ ở đây rằng uint là một unsigned int, không phải là một unassigned int. Sự khác biệt lớn!

-2

Lý do nó kết thúc thành tiêu cực là do Two's Complement phép toán được sử dụng cho số học số nguyên.

Câu trả lời ngắn gọn là bit quan trọng nhất được sử dụng làm dấu. Số không là dương; một là tiêu cực.

+0

uint = unsigned int – eplawless

-1

Luôn sử dụng gấp đôi.Sự khác biệt hiệu suất là không đáng kể, và nó là linh hoạt hơn và có sức chứa. Thực hành này ngăn ngừa ngoại lệ và giảm thời gian phát triển. Người hậu môn ghét nó mặc dù.

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