2016-08-08 21 views
6

Tôi có ba lớp (classA, classB và classC) kế thừa từ một giao diện 'IFoo'; nếu sử dụng nàyToán tử null-coalsescing hoạt động như thế nào

var fooItem = (request.classAitem ?? (request.classBitem as IFoo ?? request.classCitem)) 

hoặc

var fooItem = (request.classAitem ?? request.classBitem ?? request.classCitem as IFoo) 

nó hoạt động tốt nhưng kết hợp khác thậm chí sẽ không biên dịch:

var fooItem = (request.classAitem as IFoo ?? request.classBitem ?? request.classCitem) 

hoặc

var fooItem = (request.classAitem ?? request.classBitem ?? request.classCitem) as IFoo 

Dường như với tôi trong một số trường hợp, trình biên dịch ngầm y unboxes các lớp con vào giao diện IFoo của chúng nhưng trong một số trường hợp khác thì không. các bạn nghĩ sao?

+2

Các loại 'classAitem',' classBitem' và 'classCitem' là gì? Vui lòng hiển thị định nghĩa của những người đó. Ngoài ra, 'ContactPoint' là gì? Điều đó có thực hiện 'IFoo' không? – poke

+0

không thể biên dịch nhưng có lỗi gì? – Doruk

+0

Vui lòng đăng [mcve]. –

Trả lời

5

Trong cả hai ví dụ của bạn mà không làm việc, vì ?? là phải kết hợp, chúng tôi đang cố gắng đầu tiên để xác định kiểu dữ liệu của biểu thức này:

request.classBitem ?? request.classCitem 

Các kiểu dữ liệu chỉ có thể là kiểu dữ liệu của một trong các đầu vào của nó, nếu các kiểu dữ liệu khác nhau. Rõ ràng là không có chuyển đổi có sẵn ở một trong hai hướng ở đây và do đó bạn sẽ nhận được một lỗi trình biên dịch. Lưu ý rằng trình biên dịch sẽ không quyết định rằng kiểu dữ liệu ở đây là IFoo chỉ vì cả hai lớp xảy ra để thực hiện nó (và nếu nó đã làm, những gì sẽ xảy ra nếu cả hai đều thực hiện nhiều giao diện chung?)

Hãy so sánh này để bạn hai ví dụ đầu tiên. Trong lần đầu tiên, lần đầu tiên chúng ta xem xét biểu thức này:

request.classBitem as IFoo ?? request.classCitem 

Các loại biểu hiện này là một trong hai IFoo hoặc bất cứ kiểu dữ liệu của request.classCitem là. Có một chuyển đổi từ loại request.classCitem thành IFoo và do đó, điều đó rõ ràng được chọn và do đó, toàn bộ loại dữ liệu của biểu thức là IFoo. Điều đó sau đó được sử dụng để xác định loại biểu thức tổng thể (một lần nữa, IFoo).

Trường hợp thứ hai là rất giống nhau, vì ?? là đúng kết , trước hết chúng ta phải xác định loại:

request.classBitem ?? request.classCitem as IFoo 

Và một lần nữa, chúng ta có một sự lựa chọn giữa IFoo và bất cứ kiểu dữ liệu trong số request.classBitem. Có một chuyển đổi thành IFoo và do đó được chọn.

Và lưu ý, cũng có nghĩa là dấu ngoặc đơn trong ví dụ đầu tiên là thừa.

+0

Tôi thấy điểm của bạn: nó đánh giá biểu thức đầy đủ bắt đầu từ bên phải, "var fooItem = (request.classAitem là ContactPoint ?? request.classBitem ?? request.classCitem) "sẽ không hoạt động vì điều đầu tiên nó làm là đánh giá" request.classBitem ??request.classCitem "đó là unsolvable bởi vì như bạn đã nói classB và classC có thể chia sẻ bất kỳ số lượng các giao diện.Câu trả lời tuyệt vời. – Zalomon

+1

@ Zalomon - Tôi đã cẩn thận để tránh sử dụng từ" đánh giá "- bởi vì nó sẽ không * đánh giá *' classBitem' hoặc 'classCitem' ở tất cả, nếu' classAitem' không phải là 'null', nhưng những gì nó cần làm là xác định kiểu dữ liệu * của biểu thức tổng thể mà không cần xem xét các kiểu dữ liệu của tất cả các đầu vào tiềm năng. –

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