2013-05-22 37 views
13

Sau khi xem cách double.Nan == double.NaN luôn luôn là sai trong C#, tôi đã trở nên tò mò như thế nào bình đẳng đã được thực hiện dưới mui xe. Vì vậy, tôi sử dụng Resharper để biên soạn lại các cấu trúc đôi, và đây là những gì tôi thấy:Khi nào là System.Double không phải là gấp đôi?

public struct Double : IComparable, IFormattable, IConvertible, IComparable<double>, IEquatable<double> 
{ 
    // stuff removed... 

    public const double NaN = double.NaN; 

    // more stuff removed... 
} 

Điều này dường như chỉ ra các struct Double tuyên bố một hằng số được định nghĩa về trường hợp này thấp hơn đặc biệt double, mặc dù tôi d luôn nghĩ rằng hai người hoàn toàn đồng nghĩa. Hơn nữa, nếu tôi đi đến thực hiện trên đôi chữ thường, Resharper chỉ đơn giản là cuộn tôi đến khai báo ở trên cùng của tập tin. Tương tự như vậy, nhảy để thực hiện các chữ thường của NaN chỉ đưa tôi đến khai báo liên tục trước đó trong dòng!

Vì vậy, tôi đang cố gắng hiểu định nghĩa dường như đệ quy này. Đây có phải chỉ là một vật phẩm của bộ giải mã? Có lẽ một hạn chế trong Resharper? Hoặc là chữ thường đôi này thực sự là một con thú khác hoàn toàn - đại diện cho một cái gì đó ở một mức độ thấp hơn từ CLR/CTS?

Trường hợp nào NaN thực sự đến từ đâu?

+2

Đây có phải là liên quan không? http://stackoverflow.com/questions/4751885/how-are-the-primitive-types-defined-non-recursively Và cũng http://stackoverflow.com/questions/16113850/if-int32-is-just-an -alias-for-int-how-can-the-int32-class-use-an-int –

+3

Chỉ cần sử dụng VS để xem siêu dữ liệu cho thấy 'public const double NaN = 0.0/0.0;' –

+1

'NaN' có nghĩa là 'Không phải là Số' và có thể là số dương hoặc âm, giống như 'Infinity'. Trong trường hợp ai đó đang tự hỏi. – Nolonar

Trả lời

8

Đến nay, nguồn tốt nhất bạn có thể nhận được cho các hội đồng .NET là mã nguồn thực tế được sử dụng để xây dựng chúng. Beats bất kỳ decompiler cho độ chính xác, các ý kiến ​​có thể khá hữu ích là tốt. Tải xuống Reference Source.

Sau đó bạn sẽ thấy rằng Double.NaN không được định nghĩa trong IL như Marc giả định, nó thực sự nằm trong tệp mã nguồn C#.Các tập tin mã nguồn net/clr/bcl/system/double.cs cho thấy việc kê khai thực:

public const double NaN = (double)0.0/(double)0.0; 

nào lợi dụng trình biên dịch C# đánh giá biểu thức liên tục tại thời gian biên dịch. Hoặc để đưa nó vào lưỡi, NaN được định nghĩa bởi trình biên dịch C++ vì đó là ngôn ngữ được sử dụng để viết trình biên dịch C#;)

15

Hãy coi chừng việc xem mã được giải mã, đặc biệt nếu nó dành cho thứ gì đó sẵn có. Các IL thực tế ở đây (đối với .NET 4.5, ít nhất) là:

.field public static literal float64 NaN = float64(NaN) 
{ 
    .custom instance void __DynamicallyInvokableAttribute::.ctor() 
} 

ví dụ này được xử lý trực tiếp trong IL qua NaN token.

Tuy nhiên, vì đó là const (literal trong IL), nó sẽ bị "ghi vào" trang web cuộc gọi; bất kỳ nơi nào khác sử dụng double.NaN cũng sẽ cũng đang sử dụng float64(NaN). Tương tự như vậy, ví dụ, nếu tôi làm:

const int I = 2; 
int i = I; 
int j = 2; 

cả hai nhiệm vụ sẽ trông giống hệt trong IL thức (cả họ sẽ có ldc.i4.2).

Vì lý do này, hầu hết các trình giải mã sẽ nhận dạng mẫu IL NaN và biểu thị nó bằng ngôn ngữ tương đương với double.NaN. Nhưng điều đó không có nghĩa là mã tự nó đệ quy; họ có lẽ chỉ không có một kiểm tra cho "nhưng là nó double.NaN chính nó?". Cuối cùng, đây chỉ đơn giản là một trường hợp đặc biệt, trong đó float64(NaN) là một giá trị được công nhận trong IL.

Ngẫu nhiên, phản xạ dịch ngược nó như:

[__DynamicallyInvokable] 
public const double NaN = (double) 1.0/(double) 0.0; 

Đó một lần nữa không có nghĩa rằng đây là sự thật: p Chỉ rằng đây là một cái gì đó mà có thể có kết quả cuối cùng.

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