2012-08-15 8 views
28

Tôi tạo ra một "const" cho một giá trị trước đó quy định rõ ràng nhiều lần trong mã của tôi:Tại sao điều này lại biên dịch?

private static readonly int QUARTER_HOUR_COUNT = 96; 

Khi tôi đã tìm kiếm và thay thế của 96 cho QUARTER_HOUR_COUNT, tôi vô tình cũng thay thế tờ khai, vì vậy nó đã trở thành:

private static readonly int QUARTER_HOUR_COUNT = QUARTER_HOUR_COUNT; 

... chưa được biên dịch. Tôi sẽ nghĩ rằng nó sẽ không cho phép điều đó. Tại sao nó được trình biên dịch chấp nhận như một khai báo hợp lệ?

+0

Bởi vì nó là tĩnh! – canon

+0

Wow! Đó là hành vi đáng ngạc nhiên. – leppie

+0

vì có vô số cách để làm sai. – Jodrell

Trả lời

23

I would think that it would disallow that. Why was it accepted by the compiler as a valid declaration?

Có lẽ vì đặc tả ngôn ngữ cho phép. Bạn có quy tắc cụ thể trong đặc tả ngôn ngữ mà bạn cho là cấm không?

Nếu câu hỏi của bạn thực sự là "tại sao đặc tả ngôn ngữ lại không cho phép điều này" - tôi nghi ngờ là vì nó có thể khá khó khăn để đảm bảo bạn chỉ cấm những thứ bạn thực sự muốn cấm, trong khi thực sự cấm tất cả những thứ như vậy .

Bạn có thể tranh luận rằng cho trường hợp đơn giản của phân công trực tiếp trở lại chính nó, nó sẽ là tốt để có một trường hợp đặc biệt trong spec ngôn ngữ, nhưng nó sẽ giới thiệu phức tạp sang ngôn ngữ cho tương đối lợi ích nhỏ.

Lưu ý rằng ngay cả khi bạn không nhận được một lỗi , tôi mong đợi bạn để có được một cảnh báo - một cái gì đó như thế này:

Test.cs(3,33): warning CS1717: Assignment made to same variable; did you mean to assign something else?

Cũng lưu ý rằng nếu bạn thực hiện nó một const thay vì chỉ là một biến readonly tĩnh, sau đó bạn làm nhận được một lỗi thời gian biên dịch:

Test.cs(3,23): error CS0110: The evaluation of the constant value for 'Program.QUARTER_HOUR_COUNT' involves a circular definition

Cũng lưu ý rằng bằng cách ước NET đặt tên, điều này phải được gọi là QuarterHourCount, thay vì có SHOUTY_NAME.

+1

Cách sử dụng biến không được gán tôi đã nghĩ. – leppie

+3

@leppie: Không dành cho các trường tĩnh trong bộ khởi tạo trường tĩnh. Thuật ngữ "Biến không được gán" không liên quan đến các trường tĩnh, không có khái niệm phân bổ xác định. –

+0

Trên thực tế, chúng được khởi tạo theo thứ tự chúng được xác định. IMO này vi phạm quy tắc đó. – leppie

5

Vì biến được khởi tạo là 0 và sau đó đặt thành chính nó.

Dự đoán của tôi là nó sẽ làm một Int() mới trước khi thiết lập cho chính nó mà sẽ khởi tạo nó bằng không.

4

Bởi vì trình biên dịch sẽ phá vỡ dòng này xuống:

private static readonly int QUARTER_HOUR_COUNT = QUARTER_HOUR_COUNT; 

Về cơ bản vào tương đương IL của:

private static readonly int QUARTER_HOUR_COUNT; 
QUARTER_HOUR_COUNT = QUARTER_HOUR_COUNT; 

Và sau đó rõ ràng rằng sẽ nhận được chia nhỏ quá nhiều, nhưng nên ở trên đủ để minh họa quan điểm của tôi.

Vì vậy, về mặt kỹ thuật, nó sẽ tồn tại với giá trị mặc định bằng 0 tại thời điểm được sử dụng.

0

Khi những người khác đã ngụ ý các loại giá trị như int có giá trị mặc định để khai báo một biến mà không khởi tạo rõ ràng nó có nghĩa là nó vẫn có giá trị.

Bạn có thể tìm hiểu các giá trị mặc định cho bất kỳ loại như vậy:

int i = default(int); 

Hoặc tổng quát hơn:

T t = default(T); 

Lưu ý rằng đối với các loại tài liệu tham khảo các mặc định sẽ được null, chỉ có các loại giá trị sẽ có giá trị mặc định.

6

Mã IL được tạo ra bởi mã là thế này:

IL_0007: ldsfld  int32 Example.Quat::QUARTER_HOUR_COUNT//Load the value of a static field on the stack 
IL_000c: stsfld  int32 Example.Quat::QUARTER_HOUR_COUNT// Store the value from the stack in the static field 

Kể từ khi giá trị mặc định của QUARTER_HOUR_COUNT là 0, 0 được gán cho QUARTER_HOUR_COUNT