Casting en datatypeconversies in VB.NET

Casten is het proces waarbij het ene gegevenstype naar een ander wordt geconverteerd, bijvoorbeeld van een type Integer naar een tekenreekstype. Sommige bewerkingen in VB.NET vereisen specifieke gegevenstypen om te werken. Casting maakt het type dat u nodig hebt. Het eerste artikel in deze tweedelige serie, Casting en Data Type Conversions in VB.NET, introduceert casting. Dit artikel beschrijft de drie operators die u kunt gebruiken om in VB.NET te casten - DirectCast, CType en TryCast - en vergelijkt hun prestaties.

Prestaties is een van de grote verschillen tussen de drie castingoperatoren volgens Microsoft en andere artikelen. Microsoft let er bijvoorbeeld meestal op dat "DirectCast ... iets betere prestaties kan bieden dan CType bij het converteren naar en van het gegevenstype Object."(Nadruk toegevoegd.)

Ik besloot om wat code te schrijven om te controleren.

Maar eerst een woord van waarschuwing. Dan Appleman, een van de oprichters van de technische boekuitgever Apress en een betrouwbare technische goeroe, vertelde me ooit dat benchmarkingprestaties veel moeilijker te doen zijn dan de meeste mensen zich realiseren. Er zijn factoren zoals machineprestaties, andere processen die mogelijk parallel worden uitgevoerd, optimalisatie zoals geheugencaching of compileroptimalisatie en fouten in uw veronderstellingen over wat de code eigenlijk doet. In deze benchmarks heb ik geprobeerd vergelijkingsfouten bij "appels en sinaasappels" te elimineren en alle tests zijn uitgevoerd met de release build. Maar er kunnen nog steeds fouten in deze resultaten voorkomen. Laat het me weten als je iets opmerkt.

De drie castingoperators zijn:

  • DirectCast
  • CType
  • TryCast

In de praktijk zult u meestal merken dat de vereisten van uw toepassing bepalen welke operator u gebruikt. DirectCast en TryCast hebben zeer beperkte vereisten. Wanneer u DirectCast gebruikt, moet het type al bekend zijn. Hoewel de code ...

theString = DirectCast (theObject, String)

… Zal succesvol compileren als theObject al geen string is, dan zal de code een runtime-uitzondering genereren.

TryCast is nog beperkter omdat het helemaal niet werkt op "waarde" -typen zoals Integer. (String is een referentietype. Zie het eerste artikel in deze serie voor meer informatie over waardetypen en referentietypen.) Deze code ...

theInteger = TryCast (theObject, Integer)

... zal niet eens compileren.

TryCast is handig als u niet zeker weet met welk type object u werkt. In plaats van een fout als DirectCast te gooien, retourneert TryCast gewoon niets. De normale praktijk is om voor niets te testen na het uitvoeren van TryCast.

Alleen CType (en de andere "Convert" -operatoren zoals CInt en CBool) zullen types die geen overervingsrelatie hebben, zoals een geheel getal, converteren naar een string:

 Dim theString As String = "1" Dim theInteger As Integer theInteger = CType (theString, Integer) 

Dit werkt omdat CType "helpfuncties" gebruikt die geen deel uitmaken van .NET CLR (Common Language Runtime) om deze conversies uit te voeren.

Maar onthoud dat CType ook een uitzondering genereert als theString niet iets bevat dat kan worden geconverteerd naar een geheel getal. Als er een mogelijkheid is dat de string geen geheel getal als dit is ...

 Dim theString As String = "George" 

... dan werkt geen enkele castingoperator. Zelfs TryCast werkt niet met Integer omdat het een waardetype is. In een geval als dit zou u geldigheidscontrole, zoals de TypeOf-operator, moeten gebruiken om uw gegevens te controleren voordat u deze probeert te casten.

De documentatie van Microsoft voor DirectCast vermeldt specifiek casten met een objecttype, dus dat heb ik in mijn eerste prestatietest gebruikt. Het testen begint op de volgende pagina!

DirectCast gebruikt meestal een objecttype, dus dat heb ik in mijn eerste prestatietest gebruikt. Om TryCast in de test op te nemen, heb ik ook een If-blok opgenomen, omdat bijna alle programma's die TryCast gebruiken er een hebben. In dit geval zal het echter nooit worden uitgevoerd.

Hier is de code die alle drie vergelijkt bij het casten van een object naar een string:

 Dim theTime As New Stopwatch () Dim theString As String Dim theObject As Object = "An Object" Dim theIterations As Integer = CInt (Iterations.Text) * 1000000 "DirectCast Test theTime.Start () Voor i = 0 Naar theIterations theString = DirectCast (theObject, String) Volgende theTime.Stop () DirectCastTime.Text = theTime.ElapsedMilliseconds.ToString "CType Test theTime.Restart () Voor i As Integer = 0 Naar theIterations theString = CType (theObject, String) Volgende theTime.Stop () CTypeTime.Text = theTime.ElapsedMilliseconds.ToString "TryCast Test theTime.Restart () For i As Integer = 0 To theIterations theString = TryCast (theObject, String) Als theString niets is dan MsgBox (" Dit zou nooit moeten worden weergegeven ") Einde als volgende theTime.Stop () TryCastTime.Text = theTime.ElapsedMilliseconds.ToString 

Deze eerste test lijkt aan te tonen dat Microsoft gelijk heeft. Hier is het resultaat. (Experimenten met grotere en kleinere aantallen iteraties evenals herhaalde tests onder verschillende omstandigheden toonden geen significante verschillen met dit resultaat.)

--------
Klik hier om de illustratie weer te geven
--------

DirectCast en TryCast waren vergelijkbaar op 323 en 356 milliseconden, maar CType nam drie keer zoveel tijd in beslag op 1018 milliseconden. Bij het casten van referentietypes zoals deze betaal je voor de flexibiliteit van CType in prestaties.

Maar werkt het altijd zo? Het Microsoft-voorbeeld op hun pagina voor DirectCast is vooral nuttig om u te vertellen wat zal niet werk met behulp van DirectCast, niet wat wil. Hier is het Microsoft-voorbeeld:

 Dim q As Object = 2.37 Dim i As Integer = CType (q, Integer) 'De volgende conversie mislukt tijdens uitvoering Dim j As Integer = DirectCast (q, Integer) Dim f als nieuw System.Windows.Forms.Form Dim c As System.Windows.Forms.Control 'De volgende conversie slaagt. c = DirectCast (f, System.Windows.Forms.Control) 

Met andere woorden, jij kan niet gebruik DirectCast (of TryCast, hoewel ze het hier niet vermelden) om een ​​objecttype naar een geheel getal te casten, maar u kan gebruik DirectCast om een ​​formuliertype naar een controletype te casten.

Laten we eens kijken naar de prestaties van het voorbeeld van Microsoft van wat zullen werken met DirectCast. Gebruik dezelfde codesjabloon als hierboven, vervang ...

 c = DirectCast (f, System.Windows.Forms.Control) 

... in de code, samen met vergelijkbare vervangingen voor CType en TryCast. De resultaten zijn een beetje verrassend.

--------
Klik hier om de illustratie weer te geven
--------

DirectCast was eigenlijk de langzaamste van de drie keuzes bij 145 milliseconden. CType is net iets sneller met 127 milliseconden, maar TryCast, inclusief een If-blok, is het snelst met 77 milliseconden. Ik heb ook geprobeerd mijn eigen objecten te schrijven:

 Klasse ParentClass ... Einde Klasse Klasse ChildClass Inherits ParentClass ... Einde Klasse 

Ik heb vergelijkbare resultaten. Het lijkt erop dat als jij dat bent niet een objecttype casten, bent u beter af niet met behulp van DirectCast.