Casting to proces konwersji jednego typu danych na inny, na przykład z typu Integer na typ String. Niektóre operacje w VB.NET wymagają określonych typów danych do pracy. Przesyłanie tworzy typ, którego potrzebujesz. Pierwszy artykuł z tej dwuczęściowej serii, Przesyłanie i konwersje typów danych w VB.NET, przedstawia rzutowanie. W tym artykule opisano trzech operatorów, których możesz użyć do przesyłania VB.NET - DirectCast, CType i TryCast - i porównuje ich wydajność.
Wydajność jest jedną z dużych różnic między trzema operatorami rzutowania według Microsoft i innych artykułów. Na przykład Microsoft zwykle ostrożnie ostrzega, że „DirectCast... może zapewnić nieco lepszą wydajność niż CType podczas konwersji do iz typu danych Object. ”(Podkreślenie dodane.)
Postanowiłem napisać kod do sprawdzenia.
Ale najpierw słowo ostrzeżenia. Dan Appleman, jeden z założycieli wydawcy książek technicznych Apress i niezawodny specjalista techniczny guru, kiedyś powiedział mi, że wydajność testów porównawczych jest dużo trudniejsza do wykonania poprawnie niż większość ludzi realizować. Istnieją czynniki, takie jak wydajność maszyny, inne procesy, które mogą być uruchomione równolegle, optymalizacja takie jak buforowanie pamięci lub optymalizacja kompilatora oraz błędy w twoich założeniach dotyczących tego, czym właściwie jest kod robić. W tych testach próbowałem wyeliminować błędy porównania „jabłek i pomarańczy”, a wszystkie testy zostały uruchomione z kompilacją wydania. Ale nadal mogą występować błędy w tych wynikach. Jeśli zauważysz jakieś, daj mi znać.
Trzej operatorzy odlewów to:
- DirectCast
- CTyp
- TryCast
W praktyce zazwyczaj okaże się, że wymagania Twojej aplikacji określą, którego operatora używasz. DirectCast i TryCast mają bardzo wąskie wymagania. Gdy używasz DirectCast, typ musi być już znany. Chociaż kod ...
theString = DirectCast (theObject, String)
... skompiluje się pomyślnie, jeśli obiekt nie jest już ciągiem, wówczas kod zgłosi wyjątek czasu wykonywania.
TryCast jest jeszcze bardziej restrykcyjny, ponieważ nie działa w ogóle na typach „wartościowych”, takich jak liczba całkowita. (String jest typem odniesienia. Więcej informacji na temat typów wartości i typów referencji znajduje się w pierwszym artykule z tej serii.) Ten kod ...
theInteger = TryCast (theObject, Integer)
... nawet się nie skompiluje.
TryCast jest przydatny, gdy nie jesteś pewien, z jakim typem obiektu pracujesz. Zamiast zgłaszać błąd, taki jak DirectCast, TryCast po prostu zwraca Nic. Normalną praktyką jest testowanie na nic po uruchomieniu TryCast.
Tylko CType (i inne operatory „Konwertuj”, takie jak CInt i CBool) konwertują typy, które nie mają relacji dziedziczenia, takie jak liczba całkowita na ciąg:
Dim theString As String = "1" Dim theInteger As Integer. theInteger = CType (theString, Integer)
Działa to, ponieważ CType używa „funkcji pomocniczych”, które nie są częścią .NET CLR (Common Language Runtime) do wykonania tych konwersji.
Pamiętaj jednak, że CType wyrzuci również wyjątek, jeśli ciąg nie zawiera czegoś, co można przekonwertować na liczbę całkowitą. Jeśli istnieje możliwość, że ciąg nie jest liczbą całkowitą taką jak ta ...
Dim theString As String = "George"
... wtedy żaden operator rzutowania nie będzie działał. Nawet TryCast nie będzie działać z Integer, ponieważ jest to typ wartości. W takim przypadku należy użyć sprawdzania poprawności, takiego jak operator TypeOf, aby sprawdzić dane przed próbą ich rzutowania.
Dokumentacja Microsoftu dla DirectCast wspomina konkretnie rzutowanie z typem obiektu, więc tego właśnie użyłem w pierwszym teście wydajności. Testy rozpoczynają się na następnej stronie!
DirectCast zwykle używa typu Object, więc tego właśnie użyłem podczas pierwszego testu wydajności. Aby uwzględnić TryCast w teście, dołączyłem również blok If, ponieważ prawie wszystkie programy używające TryCast będą go miały. W takim przypadku jednak nigdy nie zostanie wykonane.
Oto kod, który porównuje wszystkie trzy podczas rzutowania obiektu na ciąg znaków:
Dim theTime As New Stopwatch () Dim theString As String. Dim theObject As Object = "Obiekt" Dim theIterations As Integer = CInt (Iteracje. Tekst) * 1000000. ' „Test DirectCast. czas. Początek() Dla i = 0 do iteracji. theString = DirectCast (theObject, String) Kolejny. czas. Zatrzymać() DirectCastTime. Tekst = czas. ElapsedMilliseconds. ToString. ' „Test typu. czas. Uruchom ponownie () Dla i jako liczba całkowita = 0 do iteracji. theString = CType (theObject, String) Kolejny. czas. Zatrzymać() CTypeTime. Tekst = czas. ElapsedMilliseconds. ToString. ' „Test TryCast. czas. Uruchom ponownie () Dla i jako liczba całkowita = 0 do iteracji. theString = TryCast (theObject, String) Jeśli ciąg jest niczym, to. MsgBox („To nigdy nie powinno się wyświetlać”) End If. Kolejny. czas. Zatrzymać() TryCastTime. Tekst = czas. ElapsedMilliseconds. ToString.
Ten wstępny test wydaje się wskazywać, że Microsoft ma rację. Oto wynik. (Eksperymenty z większą i mniejszą liczbą iteracji, a także powtarzane testy w różnych warunkach nie wykazały żadnych istotnych różnic w stosunku do tego wyniku).
Kliknij tutaj, aby wyświetlić ilustrację
DirectCast i TryCast były podobne przy 323 i 356 milisekundach, ale CType zajęło trzy razy więcej czasu przy 1018 milisekundach. Rzucając takie typy referencyjne, płacisz za elastyczność CType pod względem wydajności.
Ale czy to zawsze działa w ten sposób? Przykład Microsoft na ich stronie dla DirectCast jest użyteczny głównie do powiedzenia ci, co przyzwyczajenie pracować przy użyciu DirectCast, a nie co będzie. Oto przykład Microsoft:
Dim q As Object = 2,37. Dim i As Integer = CType (q, Integer) „Następująca konwersja kończy się niepowodzeniem w czasie wykonywania. Dim j As Integer = DirectCast (q, Integer) Dim f As New System. Windows Formularze Formularz. Dim c As System. Windows Formularze Kontrola. „Następująca konwersja kończy się powodzeniem. c = DirectCast (f, System. Windows Formularze Kontrola)
Innymi słowy, ty żargon użyj DirectCast (lub TryCast, chociaż nie wspominają o tym tutaj), aby rzutować typ Object na Integer, ale mogą użyj DirectCast, aby rzutować typ formularza na typ kontrolny.
Sprawdźmy wydajność przykładu Microsoft Wola praca z DirectCast. Używając tego samego szablonu kodu pokazanego powyżej, zastąp ...
c = DirectCast (f, System. Windows Formularze Kontrola)
... do kodu wraz z podobnymi podstawieniami dla CType i TryCast. Wyniki są trochę zaskakujące.
Kliknij tutaj, aby wyświetlić ilustrację
DirectCast był w rzeczywistości najwolniejszym z trzech wyborów w 145 milisekundach. CType jest tylko trochę szybszy przy 127 milisekundach, ale TryCast, w tym blok If, jest najszybszy przy 77 milisekundach. Próbowałem też pisać własne obiekty:
Klasa ParentClass... Klasa końcowa. Klasa ChildClass. Dziedziczy ParentClass... Klasa końcowa.
Mam podobne wyniki. Wygląda na to, że jeśli jesteś nie rzucając typ obiektu, lepiej nie przy użyciu DirectCast.