Pytanie w sprawie .net-4.0, clr, c#, casting – C # casting to nullable type?

28

Poza regularna nudna różnica międzyCast iAs

Jeśli jawiedzieć żejabłko jestOwoc więc mogę użyć(Fruit)apple - i rzuca wyjątek, jeśli nieas value można sprawdzić przeciwko null, aby zobaczyć, czy się udało [nie rzuci wyjątku ...]

Jednak czytałem @EricLippertartykuł o tym i była fajna próbka o Nullable Value Types:

<code>short? s = (short?)123;
int? i = s as int?;
</code>

toprzyzwyczajenie skompilować...

Nie można przekonwertować typu „krótki”? na „int?” poprzez konwersję referencyjną, konwersję boksu, konwersję rozpakowywania, konwersję zawijania lub konwersję typu zerowego

W porządku.

więc dlaczego to:

<code>    short? s = (short?)123;
    int? i = (int?)s;
</code>

Robi Skompilować? (Przeciwko wszystkim oczekiwaniom ! jaWIEDZIEĆ żes nie jestint? - i powinno pójść BANG, ale to nie ...)

sprawdzanie Cast tutaj powinno być znacznie bardziej zabójcze niż poprzedni przykład (który przeszedł Bang)

Źle się pytam o ten bardzo głośny temat.

Z góry dziękuję.

@RoyiNamir, twoja parafraza MrListera jest całkiem bliska poprawności. Jest jednak ryzykowne, ponieważ „wartość” i „referencja” nie mają tu nic wspólnego z wartością C # w stosunku do typów referencyjnych. sblom
Ok, myślę, że zrozumiałem, o co pytasz ... Spróbujmy: nie jest(int?)zadanie rzucenia kiedys nie jestint?. Jego zadaniem jest rzucić jeślis nie jestzamienny doint?. Tam sąwiele przypadki gdzie(type)casting w stylu może robić inne rzeczy niż tylko testowanie, czy masz ten typ (na przykład możesz nawet zdefiniować własny -msdn.microsoft.com/en-us/library/xhbhezf4(v=vs.100).aspx). Jeśli naprawdę chcesz przetestować, aby sprawdzić, czy masz rzeczywistą instancję typu, powinieneś użyćis operator. sblom
I jeszcze jedno -int? i2 = (object)s as int?; - faktycznie wracanull NSGaga
@MrLister Mówisz mi to(int?)s jest operacją wartości (w przeciwieństwie do [as], która jest operacją referencyjną)? Royi Namir

Twoja odpowiedź

4   odpowiedź
25

W twoim pierwszym przykładzieas operator próbuje użyć obiektus jakoint?. Odint? nie jest nigdzie w łańcuchu dziedziczeniashort?, ta operacja nie powiedzie się.

W drugim przykładzie tworzysz nowyint? i z wartością zshort? s. Jest to bardziej hojna operacja, ponieważ nie musi zachowywać oryginałus obiekt po lewej stronie.

Ważne jest tutaj toas nie wolno robić niczego, co nie chroni tożsamości twojego obiektu. Wyraźna obsada może.

Oto, co mówi standard C # o tym, jak(int?) forma działa:

6.1.4 Niejawne, nieważne konwersje

Predefiniowane konwersje niejawne, które działają na typach wartości niezawierających wartości null, mogą być również używane z formami dopuszczającymi wartości zerowe tych typów. Dla każdej z predefiniowanych niejawnych konwersji tożsamości i liczb, które konwertują wartość niezerową typu S na wartość niezawierającą wartości typu T, istnieją następujące niejawne konwersje dopuszczające wartość pustą:

· Niejawna konwersja z S? do T ?.

· Niejawna konwersja z S na T ?.

Ocena domniemanej konwersji z wyłączeniem wartości dopuszczalnej opartej na konwersji bazowej z S na T przebiega następująco:

· Jeśli konwersja dopuszczalna jest z S? do T ?:

o Jeśli wartość źródłowa ma wartość null (właściwość HasValue ma wartość false), wynikiem jest wartość null typu T ?.

o W przeciwnym razie konwersja jest oceniana jako rozpakowanie z S? do S, po którym następuje konwersja z S na T, po której następuje zawijanie (§4.10.10) z T na T ?.

· Jeśli konwersja dopuszczalna jest od S do T?, Konwersja jest oceniana jako podstawowa konwersja z S na T, po której następuje zawijanie od T do T ?.

@sblom Myślę, że powinieneśdouble-bold powyższy akapit mówiThe important point here is that as isn't allowed to do anything that doesn't preserve your object's identity. An explicit cast can. - Myślę, że to jest sedno tego. Zgadzam się, a jeśli chodzi o casting, to dla mnie jasne (as tak naprawdę nie było), i jak Eric powiedział, że nie ma arytmetyki na short-s (nie ma to większego znaczenia, ale jest łatwiejsze do zrozumienia, przynajmniej dla mnie, konwersji), przekształca się w int. NSGaga
@RoyiNamir, naprawdę nie rozumiem. Istnieje konwersja zshort doint (to prawda w języku C, Java i prawie wszędzie), a specyfikacja C # opisuje, jak wykonać tę konwersję i sprawić, by działała na typach dopuszczalnych. (Dodałem odpowiedni fragment powyżej.) sblom
poza tym wyjaśnieniem wciąż jest ta linia(int?)s które odnoszą się do epoki dziedziczenia / boksu .... ale działa i to jest rzecz, której nie rozumiem. Royi Namir
4

Przykład:

<code>int? i = (int?)s;
</code>

Robi kompilator, ponieważ obsada mówi kompilatorowi, że wiesz coś, czego nie można wywnioskowaćs można przekonwertować na aint?.

Wyjątek otrzymasz tylko w czasie wykonywania, jeśli rzut nie powiedzie się.

@RoyiNamir - Przepraszam, powinienem dodać, że tylko w przypadku, gdy obsada nie działa. Oded
nie ma wyjątku w czasie wykonywania ..... Royi Namir
0

System.Nullable<int> (System.Nullable<T> jest typ). Jednak krótki typ definiuje jawny rzut na intSystem.Nullable<T> nie ma takiej wyraźnej obsady, ponieważ T może być dowolnym innym typem wartości.

0

as niepowodzenie otrzymasz „ważny”null wynik, takfałszywie pozytywne. W drugim przypadku obsada jest dozwolona, ​​ponieważ w przypadku awarii spowoduje wyjątek.

Powiązane pytania