Điều này trông giống như một lỗi trong việc nâng lên vô số toán hạng trên các cấu trúc chung.Tại sao các cấu trúc chung và phi chung được xử lý khác nhau khi xây dựng biểu thức nâng vận hành == thành vô hiệu?
Hãy xem xét các cấu trúc giả sau, đó sẽ ghi đè operator==
:
Bây giờ xem xét các khái niệm sau:
Expression<Func<MyStruct, MyStruct, bool>> exprA =
(valueA, valueB) => valueA == valueB;
Expression<Func<MyStruct?, MyStruct?, bool>> exprB =
(nullableValueA, nullableValueB) => nullableValueA == nullableValueB;
Expression<Func<MyStruct?, MyStruct, bool>> exprC =
(nullableValueA, valueB) => nullableValueA == valueB;
Cả ba biên dịch và chạy như mong đợi.
Khi họ đang biên soạn (sử dụng .Compile()
) họ sản xuất các đoạn mã sau (diễn giải để tiếng Anh từ IL):
Khái niệm đầu tiên mà chỉ mất
MyStruct
(không nullable) args, chỉ cần gọiop_Equality
(việc triển khai của chúng tôi làoperator ==
)Biểu thức thứ hai, khi được biên dịch, tạo mã kiểm tra từng đối số để xem liệu nó có phải là
HasValue
hay không. Nếu cả hai không (cả hai đều bằngnull
), trả vềtrue
. Nếu chỉ có một giá trị, trả vềfalse
. Nếu không, hãy gọi sốop_Equality
trên hai giá trị.Biểu thức thứ ba kiểm tra đối số rỗng để xem nó có giá trị không - nếu không, trả về false. Nếu không, hãy gọi số
op_Equality
.
Cho đến nay rất tốt.
Bước tiếp theo: làm chính xác những điều tương tự với một kiểu generic - thay đổi MyStruct
để MyStruct<T>
ở khắp mọi nơi trong định nghĩa của các loại, và thay đổi nó để MyStruct<int>
trong biểu thức.
Bây giờ biểu thức thứ ba biên dịch nhưng ném một ngoại lệ thời gian chạy InvalidOperationException
với thông báo sau:
Các toán hạng cho nhà điều hành 'bình đẳng' không phù hợp với các thông số của phương pháp 'op_Equality'.
Tôi hy vọng các cấu trúc chung sẽ hoạt động chính xác giống như các cấu trúc không chung chung, với tất cả các nâng không có mô tả ở trên.
Vì vậy, câu hỏi của tôi là:
- Tại sao lại có một sự khác biệt giữa cấu trúc chung và không chung chung?
- Ý nghĩa của ngoại lệ này là gì?
- Đây có phải là lỗi trong C# /. NET không?
Mã đầy đủ để tái tạo này là available on this gist.
Bạn cũng có thể đăng mã đã sửa đổi của mình không? Có vẻ như bạn có thể đã bỏ lỡ một điểm khi sao chép 'MyStruct' thay cho 'MyStruct'. –
dasblinkenlight
Tôi đã thêm [gist] (https://gist.github.com/anonymous/5664417) bằng mã đầy đủ, cũng đã thêm một liên kết ở cuối câu hỏi. – sinelaw