2010-05-10 20 views
8

Tôi có một cấu trúc như thế này, với một chuyển đổi rõ ràng để float:Tại sao tôi cần chuyển đổi trung gian để chuyển từ cấu trúc sang thập phân, nhưng không phải là struct thành int?

struct TwFix32 
{ 
    public static explicit operator float(TwFix32 x) { ... } 
} 

tôi có thể chuyển đổi một TwFix32 để int với một dàn diễn viên rõ ràng duy nhất: (int)fix32

Tuy nhiên, để chuyển đổi nó sang thập phân, tôi có để sử dụng hai phôi: (decimal)(float)fix32

Không có chuyển đổi ngầm từ phao sang int hoặc thập phân. Tại sao trình biên dịch lại cho phép tôi bỏ qua phần dàn diễn viên trung gian để trôi nổi khi tôi đi vào int, nhưng không phải khi tôi chuyển sang thập phân?

Trả lời

8

Tôi thường mất một câu trả lời thỏa đáng cho câu hỏi "tại sao".

Lý do trình biên dịch C# thể hiện hành vi đó là bởi vì nó là (trong trường hợp này ít nhất (*)) thực hiện chính xác đặc tả C#.

Mục 6.4.5 của đặc tả mô tả cách phân tích chuyển đổi do người dùng xác định. Việc đọc cẩn thận phần đó sẽ giải thích tại sao chuyển đổi rõ ràng thành int là hợp pháp nhưng không phải là số thập phân.

Cụ thể, đoạn có liên quan là:

Tìm tập các đối người dùng xác định và dỡ bỏ các nhà khai thác chuyển đổi, U. bộ này bao gồm các nhà khai thác chuyển đổi ngầm hay rõ ràng người dùng xác định và dỡ bỏ tuyên bố của các lớp hoặc cấu trúc trong D chuyển đổi từ kiểu bao bọc hoặc bao bọc bởi S thành kiểu bao trùm hoặc bao trùm bởi T. Nếu U trống, chuyển đổi không xác định và xảy ra lỗi biên dịch.

Trong trường hợp của bạn, S là TwFix và T là int hoặc thập phân. Chuyển đổi rõ ràng do người dùng định nghĩa trên TwFix trả về một float. int được bao phủ bởi float, nhưng số thập phân không được bao hàm bởi cũng không bao gồm float. Do đó, tập U có một thành viên trong một trường hợp và rỗng trong trường hợp kia. Do đó một trường hợp tạo ra một lỗi, như đặc điểm kỹ thuật nói để làm, và trường hợp khác không.

Tôi có cảm giác rằng câu trả lời này không thỏa đáng. Nếu không, bạn có thể thuật lại câu hỏi sao cho nó không có từ "tại sao" trong đó? Tôi tốt hơn rất nhiều khi trả lời câu hỏi "gì" hoặc "cách" hơn là "tại sao" câu hỏi.

(*) Trình biên dịch đã biết các lỗi trong mã tính toán một loại bao gồm một loại khác cho mục đích xác định chuyển đổi tích hợp nào có liên quan khi phân tích ngữ nghĩa của một chuyển đổi do người dùng xác định cụ thể. Trong nhiều trường hợp, chúng tôi cố ý không sửa các lỗi này vì làm như vậy sẽ giới thiệu một thay đổi đột phá trong mã thực trong thế giới vì không có lợi ích lớn. Tôi rất muốn xem lại phần này của đặc tả và viết lại nó để loại bỏ khái niệm "loại bao gồm"; đó là một chút kỳ quặc trong spec. Và, như bạn đã khám phá, nó tạo ra sự kỳ quặc này, nơi float được chuyển đổi rõ ràng thành thập phân và thập phân rõ ràng có thể chuyển đổi thành float, nhưng vì không bao gồm phần tử khác, mã chuyển đổi rõ ràng do người dùng xác định không thích nó. Tuy nhiên đây là ưu tiên rất thấp.

+1

Cảm giác của tôi là câu hỏi cơ bản là tại sao (vâng, tôi biết) thực tế là có chuyển đổi ngầm từ int sang phao sẽ ảnh hưởng đến chuyển đổi xảy ra theo hướng ngược lại (TwFix32 để chuyển sang int). Điều này khiến tôi thích nó * nên * là một sự chuyển đổi không liên quan trong trường hợp này - nhưng rõ ràng là không, bởi vì nó ảnh hưởng đến sự bao trùm.Tôi nghi ngờ * * thực sự "tại sao" câu trả lời ở đây có thể là, "Bởi vì nó làm cho nhiều trường hợp khác làm việc như mong đợi, với chi phí của loại kỳ quặc này." –

+1

@Jon: Đúng; nếu bạn nghĩ về các quy tắc này từ quan điểm phân tích chuyển đổi do người dùng xác định trên các loại * tham chiếu *, điều đó có ý nghĩa hơn; các loại tham chiếu không giao diện thường không có các tình huống như tình huống float/decimal. –

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