2016-08-08 25 views
6

Mam trzy klasy (klasa A, klasa B i klasa C), które dziedziczą po interfejsie "IFoo"; jeśli to wykorzystaćJak działa operator wygaszania łańcucha

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

lub

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

to działa dobrze, ale inne kombinacje nie będzie nawet skompilować:

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

lub

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

Wydaje mi w niektórych przypadkach kompilator implicitl y unboxes klasy potomne do ich interfejsu IFoo, ale w niektórych innych przypadkach nie. Co wy myślicie?

+2

Jakie są typy "classAitem',' classBitem' i 'classCitem'? Proszę pokazać ich definicję. Co to jest "ContactPoint"? Czy to implementuje 'IFoo'? – poke

+0

nie można skompilować, ale z jakim błędem? – Doruk

+0

Wyślij wiadomość [mcve]. –

Odpowiedz

5

W obu swoich przykładach, które nie działają, ponieważ ?? jest prawostronne, my najpierw próbuje określić typ danych tego wyrażenia:

request.classBitem ?? request.classCitem 

Typ danych może być tylko typ danych jednego z jego wejść, jeśli typy danych są różne. Oczywiście nie ma dostępnych konwersji w obu kierunkach, więc pojawia się błąd kompilatora. Należy zauważyć, że kompilator będzie nie zdecydować, że typ danych tutaj jest IFoo tylko dlatego, że obie klasy zdarzyć jej wdrożenia (a jeśli tak, to co by się stało, gdyby oboje realizowany wiele wspólnych interfejsów?)

Porównaj to do listy pierwsze dwa przykłady. W pierwszym, najpierw rozważyć tę zależność:

request.classBitem as IFoo ?? request.classCitem 

typ tego wyrażenia jest albo IFoo lub niezależnie od typu danych request.classCitem jest. Istnieje konwersja z typu request.classCitem na IFoo i dlatego jest to oczywiście wybrane, dlatego typ danych całego wyrażenia to IFoo. To jest następnie używane do określenia rodzaju ogólnego wyrażenia (ponownie, IFoo).

Druga sprawa jest bardzo podobna, ponieważ ?? ma rację asocjacyjne , musimy najpierw ustalić typ:

request.classBitem ?? request.classCitem as IFoo 

I znowu mamy wybór między IFoo i niezależnie od typu danych z request.classBitem jest. Jest konwersja do IFoo i tak została wybrana.

Należy również zauważyć, że oznacza to, że nawiasy w pierwszym przykładzie są zbędne.

+0

Widzę twój punkt: ocenia on pełne wyrażenie zaczynając od prawej, "var fooItem = (request.classAitem as ContactPoint ?? request.classBitem ?? request.classCitem) "nie zadziała, ponieważ pierwszą rzeczą, którą robi, jest ocena" request.classBitem ??request.classCitem ", który jest nierozwiązywalny, ponieważ jak powiedziałeś, klasa B i klasa C mogą współdzielić dowolną liczbę interfejsów. Świetna odpowiedź: – Zalomon

+1

@Zalomon - Starałem się unikać używania słowa" oceń "- ponieważ nie będzie ono * oceniać *. classBitem' lub 'classCitem' w ogóle, jeśli' classAitem' nie ma wartości "null' .Ale to, co musi zrobić, to określić * typ danych * ogólnego wyrażenia, które musi uwzględniać typy danych wszystkich potencjalnych danych wejściowych. –