W C# 7.0 operator Is, a konkretniej dopasowywanie typów, zostało ulepszone. We wcześniejszych wersjach, byliśmy zmuszeni do pisania następującego kodu:
object test = 5; if(test is int) { int integerValue = (int)test; Console.WriteLine(integerValue.GetType()); Console.WriteLine(integerValue * 5); }
W wersji C#, możliwa jest uproszczona konstrukcja:
object test = 5; if(test is int integerValue) { Console.WriteLine(integerValue.GetType()); Console.WriteLine(integerValue * 5); }
Jeśli zmienna jest danego typu, automatycznie zostanie zrzutowana. Innymi słowy, za pomocą jednego operatora wykonujemy 3 operacje: sprawdzenie typu, zrzutowanie oraz wykonanie instrukcji warunkowej. W poprzednich wersjach, możliwe było zrobienie czegoś podobnego, ale powstały kod zwykłe był mniej przejrzysty.
Po skompilowaniu, kod jest skonwertowany do postaci z operatorem “as”:
object test = 5; int? num = test as int?; int integerValue = num.GetValueOrDefault(); bool hasValue = num.HasValue; if (hasValue) { Console.WriteLine(integerValue.GetType()); Console.WriteLine(integerValue * 5); }
W następnym wpisie, pokażę kilka kolejnych zmian, które pojawiły się w w obrębie dopasowywania typów.
W sumie dziwię się, czemu integerValue jest ustalane przed sprawdzeniem warunku (hasValue). Jeśli warunek będzie fałszem to niepotrzebnie będą odłożone dane na stosie.
Swojego czasu stworzyłem fluent helper, który działał podobnie – oczywiście w C# 7.0 już nie jest potrzebny 🙂
Swojego czasu stworzyłem fluent helper, ale teraz dla C$ 7.0 już będzie zbedny 🙂
https://github.com/pwasiewicz/GenericInvoker
Takie trochę teoretyzowanie ale ciekaw jestem czy ten operator jest thread-safe. Bo np. jeżeli is dopasuje wzorzec a międzyczasie inny wątek zmieni nam typ to wtedy rzutowanie się wywali podobnie jak wcześniej używanie IS a później AS.
@Tom
Ja tu bardziej widzę problem z zasięgiem tego integera. Dla mnie intuicyjnie jego zasięg powinien być wewnątrz if’a.
Swoją drogą, kod z pierwszego snippeta nie jest zbyt dobry. “is” tak naprawdę wykonuje pod maską rzutowanie. Zatem w tym przypadku używając “is”, a następnie rzutowania (int), wykonujemy operację rzutowania 2 razy. To nie jest sposób w jaki powinno się wykorzystywać “is”.
Myślę, że bardziej odpowiedni byłby w tym przypadku operator “as”.
var value = x as int?;
if (value != null)
{
// do something
}