Кастингът е процес за преобразуване на един тип данни в друг, например от тип Integer в тип String. Някои операции в VB.NET изискват специфични типове данни за работа. Кастингът създава типа, от който се нуждаете. Първата статия от тази поредица от две части, Casting и Data Type Conversion във VB.NET, въвежда кастинг. Тази статия описва трите оператора, които можете да използвате, за да участвате VB.NET - DirectCast, CType и TryCast - и сравнява тяхната производителност.
Производителността е една от големите разлики между трите оператора на кастинг според Microsoft и други статии. Например, Microsoft обикновено внимава да предупреди, че "DirectCast... може да осигури малко по-добра производителност от CType при преобразуване към и от тип данни Обект. "(Акцент добавен.)
Реших да напиша някакъв код, за да проверя.
Но първо дума за предпазливост. Дан Епълман, един от основателите на издателя на технически книги Apress и надежден техник гуру, веднъж ми каза, че сравнителното изпълнение е много по-трудно да се направи правилно от повечето хора осъзнават. Има фактори като производителност на машината, други процеси, които може да работят паралелно, оптимизация като кеширане на памет или оптимизация на компилатора и грешки в предположенията ви за това какво всъщност представлява кодът прави. В тези показатели се опитах да премахна грешките за сравнение на "ябълки и портокали" и всички тестове бяха проведени с версията на изданието. Но все пак може да има грешки в тези резултати. Ако забележите, моля, уведомете ме.
Трите оператори за кастинг са:
- DirectCast
- CTYPE
- TryCast
На практика обикновено ще установите, че изискванията на вашата кандидатура ще определят кой оператор използвате. DirectCast и TryCast имат много тесни изисквания. Когато използвате DirectCast, типът вече трябва да бъде известен. Въпреки че кодът ...
theString = DirectCast (theObject, String)
... ще се компилира успешно, ако theObject вече не е низ, тогава кодът ще хвърли изключение по време на изпълнение.
TryCast е още по-рестриктивен, защото изобщо няма да работи при "стойностни" видове като Integer. (String е референтен тип. За повече информация за типовете стойности и референтните типове вижте първата статия от тази серия.) Този код ...
theInteger = TryCast (theObject, Integer)
... дори няма да компилирам.
TryCast е полезен, когато не сте сигурни с какъв тип обект работите. Вместо да хвърля грешка като DirectCast, TryCast просто не връща нищо. Нормалната практика е да се тества за Нищо след изпълнение на TryCast.
Само CType (и другите оператори „Конвертиране“ като CInt и CBool) ще преобразува типове, които нямат наследствено отношение, като Integer в String:
Затъмнете theString като String = "1" Затъмнете Integer като Integer. theInteger = CType (theString, Integer)
Това работи, защото CType използва „помощни функции“, които не са част от .NET CLR (Common Language Runtime) за извършване на тези преобразувания.
Но не забравяйте, че CType също ще хвърли изключение, ако theString не съдържа нещо, което може да бъде преобразувано в цяло число. Ако има възможност низът да не е цяло число като този ...
Оразмерете theString As String = "George"
... тогава нито един оператор за кастинг няма да работи. Дори TryCast няма да работи с Integer, защото е тип стойност. В случай като този, ще трябва да използвате проверка на валидността, като оператора TypeOf, за да проверите данните си, преди да се опитате да ги предавате.
В документацията на Microsoft за DirectCast специално се споменава за кастинг с тип Object, така че това използвах в първия си тест за ефективност. Тестването започва на следващата страница!
DirectCast обикновено ще използва тип Object, така че това използвах в първия си тест за ефективност. За да включа TryCast в теста, аз също включих блок If, тъй като почти всички програми, които използват TryCast, ще имат такъв. В този случай обаче той никога няма да бъде изпълнен.
Ето кода, който сравнява и трите при предаване на обект на низ:
Затемнете времето като нов хронометър () Затъмнете theString като низ. Оразмерете обекта като обект = "Обект" Загладете итерациите като цяло число = CInt (Итерации). Текст) * 1000000. ' 'DirectCast тест. времето. Старт () За i = 0 Към итерациите. theString = DirectCast (theObject, String) Следващия. времето. Спри се() DirectCastTime. Текст = времето. ElapsedMilliseconds. ToString. ' 'CType тест. времето. Рестартирам() За i като цяло число = 0 към итерациите. theString = CType (theObject, String) Следващия. времето. Спри се() CTypeTime. Текст = времето. ElapsedMilliseconds. ToString. ' 'TestCast Test. времето. Рестартирам() За i като цяло число = 0 към итерациите. theString = TryCast (theObject, String) Ако theString е нищо тогава. MsgBox ("Това никога не трябва да се показва") Край Ако. Следващия. времето. Спри се() TryCastTime. Текст = времето. ElapsedMilliseconds. ToString.
Този първоначален тест изглежда показва, че Microsoft е точно в целта. Ето резултата. (Експерименти с по-голям и по-малък брой повторения, както и повтарящи се тестове при различни условия не показват значителни разлики от този резултат.)
Щракнете тук, за да покажете илюстрацията
DirectCast и TryCast бяха подобни на 323 и 356 милисекунди, но CType отне три пъти повече време на 1018 милисекунди. Когато кастирате референтни типове като този, вие плащате за гъвкавостта на CType в изпълнението.
Но работи ли винаги по този начин? Примерът на Microsoft в тяхната страница за DirectCast е полезен главно за да ви каже какво няма да работа с DirectCast, а не какво ще. Ето примера на Microsoft:
Dim q като обект = 2,37. Dim i As Integer = CType (q, Integer) „Следното преобразуване се проваля по време на изпълнение. Dim j As Integer = DirectCast (q, Integer) Dim f като нова система. Windows. Форми. Форма. Dim c като система. Windows. Форми. Control. „Следното преобразуване е успешно. c = DirectCast (f, система. Windows. Форми. Control)
С други думи, вие не мога използвайте DirectCast (или TryCast, въпреки че тук не го споменават), за да предавате тип обект на тип Integer, но вие мога използвайте DirectCast, за да предавате формуляр на тип Control.
Нека проверим ефективността на примера на Microsoft за какво ще работи с DirectCast. С помощта на същия шаблон на кода, показан по-горе, заменете ...
c = DirectCast (f, система. Windows. Форми. Control)
... в кода заедно с подобни замествания за CType и TryCast. Резултатите са малко изненадващи.
Щракнете тук, за да покажете илюстрацията
DirectCast всъщност беше най-бавният от трите избора на 145 милисекунди. CType е само малко по-бърз със 127 милисекунди, но TryCast, включително блок If, е най-бързият при 77 милисекунди. Опитах се да напиша и свои собствени обекти:
Клас ParentClass... Краен клас Клас ChildClass. Наследява ParentClass... Краен клас
Получих подобни резултати. Изглежда, че ако сте не изхвърляйки тип обект, по-добре си не използвайки DirectCast.