Zauważyłem, że Resharper sugeruje, żebym włączył to:
if (myObj.myProp is MyType)
{
...
}
zaangażowany w to:
var myObjRef = myObj.myProp as MyType;
if (myObjRef != null)
{
...
}
Dlaczego miałby sugerować tę zmianę? Jestem przyzwyczajony do sugerowania przez Resharpera zmian optymalizacyjnych i zmian w zakresie redukcji kodu, ale wydaje mi się, że chce wziąć moje pojedyncze oświadczenie i przekształcić je w dwuwierszową.
Według MSDN :
To wyrażenie ma wartość true, jeśli spełnione są oba następujące warunki:
wyrażenie nie jest puste. wyrażenie można rzutować na typ . Oznacza to, że rzutowane wyrażenie formularza
(type)(expression)
zakończy się bez zgłaszania wyjątku.
Czy źle to czytam, czy też nie is
robię dokładnie tych samych kontroli, tylko w jednym wierszu, bez potrzeby jawnego tworzenia kolejnej zmiennej lokalnej do sprawdzenia wartości null?
MyProp
gettera po tej zmianie.Odpowiedzi:
Ponieważ jest tylko jedna obsada. Porównaj to:
do tego:
C # 7.0 obsługuje bardziej zwartą składnię przy użyciu dopasowania wzorców :
źródło
as
może być kilka nanosekund szybciej, ale uważam to za przedwczesną mikrooptymalizację.myObj
lubmyProp
może zostać zmieniona (przez inny wątek) między rzutemis
a rzutowaniem, powodując niepożądane zachowanie.as
+!= null
spowoduje również wykonanie nadpisanego!=
operatoraMyType
if zdefiniowany (nawet jeślimyObjRef
jest null). Chociaż w większości przypadków nie stanowi to problemu (zwłaszcza jeśli poprawnie go zaimplementujesz), w niektórych skrajnych przypadkach (zły kod, wydajność) może nie być pożądane. (musiałoby to być jednak dość ekstremalne )object.ReferenceEquals(null, myObjRef)
.Najlepszą opcją jest użycie dopasowania wzorców w ten sposób:
źródło
Nie ma jeszcze informacji o tym, co tak naprawdę dzieje się pod pasem. Spójrz na ten przykład:
Przekłada się to na następujący IL:
Liczy się tutaj
isinst
icastclass
połączenia - oba stosunkowo drogie. Jeśli porównasz to z alternatywą, zobaczysz, że tylkoisinst
sprawdza:Warto również wspomnieć, że typ wartości będzie używał
unbox.any
zamiastcastclass
:Należy jednak pamiętać, że niekoniecznie przekłada się to na szybszy wynik, jak widać tutaj . Nie wydaje się być poprawa ponieważ pytano jednak: odlewy wydają się być przeprowadzone tak szybko jak kiedyś, ale
as
ilinq
obecnie około 3 razy szybciej.źródło
Ostrzeżenie dla Resharper:
"Type check and direct cast can be replaced with try cast and check for null"
Oba będą działać, zależy to od tego, jak Twój kod bardziej Ci odpowiada. W moim przypadku po prostu ignoruję to ostrzeżenie:
W moim kodzie druga droga to dłuższa i gorsza wydajność.
źródło
IRunable
. Jeśli nie masz kontroli, może przydałbyś siędynamic
?Wydaje mi się, że to zależy od tego, jakie są szanse, że będzie tego typu, czy nie. Z pewnością skuteczniejsze byłoby wykonanie rzutu z przodu, gdyby obiekt był tego typu przez większość czasu. Jeśli tylko czasami jest tego typu, bardziej optymalne może być sprawdzenie najpierw za pomocą is.
Koszt utworzenia zmiennej lokalnej jest bardzo znikomy w porównaniu z kosztem sprawdzenia typu.
Czytelność i zakres są dla mnie zazwyczaj ważniejszymi czynnikami. Nie zgodziłbym się z ReSharper i użyłbym operatora „jest” tylko z tego powodu; zoptymalizować później, jeśli jest to prawdziwe wąskie gardło.
(Zakładam, że używasz tylko
myObj.myProp is MyType
raz w tej funkcji)źródło
Powinien również sugerować drugą zmianę:
w
Spowoduje to zapisanie dostępu do właściwości i rzutowania w porównaniu z oryginalnym kodem. Ale jest to możliwe tylko po zmianie
is
naas
.źródło
(MyType)
wyrzuci wyjątek, jeśli rzutowanie się nie powiedzie.as
tylko zwracanull
.is
(ten kod jest w pytaniu).Powiedziałbym, że ma to na celu utworzenie silnie wpisanej wersji myObj.myProp, która jest myObjRef. Powinno to być następnie używane, gdy odwołujesz się do tej wartości w bloku, zamiast wykonywania rzutowania.
Na przykład to:
jest lepsze niż to:
źródło