Beim Casting wird ein Datentyp in einen anderen konvertiert, z. B. von einem Integer-Typ in einen String-Typ. Für einige Vorgänge in VB.NET sind bestimmte Datentypen erforderlich. Casting erstellt den Typ, den Sie benötigen. Der erste Artikel in dieser zweiteiligen Reihe, Casting und Datentypkonvertierungen in VB.NET, enthält eine Einführung in das Casting. Dieser Artikel beschreibt die drei Operatoren, die Sie in VB.NET umwandeln können - DirectCast, CType und TryCast - und vergleicht deren Leistung.
Die Leistung ist einer der großen Unterschiede zwischen den drei Casting-Betreibern gemäß Microsoft und anderen Artikeln. Beispielsweise warnt Microsoft in der Regel vorsichtig, dass "DirectCast ... eine etwas bessere Leistung als CType bieten kann beim Konvertieren in und aus dem Datentyp Object." (Betonung hinzugefügt.)
Ich beschloss, einen Code zu schreiben, um zu überprüfen.
Aber zuerst ein Wort der Vorsicht. Dan Appleman, einer der Gründer des technischen Buchverlags Apress und ein zuverlässiger technischer Guru, sagte mir einmal, dass Benchmarking-Leistung viel schwieriger ist, als die meisten Menschen erkennen. Es gibt Faktoren wie die Maschinenleistung, andere Prozesse, die möglicherweise parallel ausgeführt werden, Optimierungen wie Speicher-Caching oder Compiler-Optimierung sowie Fehler in Ihren Annahmen darüber, was der Code tatsächlich tut. In diesen Benchmarks habe ich versucht, "Äpfel und Apfelsinen" -Vergleichsfehler zu beseitigen, und alle Tests wurden mit dem Release-Build ausgeführt. Diese Ergebnisse können jedoch noch fehlerhaft sein. Wenn Sie etwas bemerken, lassen Sie es mich bitte wissen.
Die drei Casting-Operatoren sind:
In der Praxis werden Sie normalerweise feststellen, dass die Anforderungen Ihrer Anwendung bestimmen, welchen Operator Sie verwenden. DirectCast und TryCast haben sehr enge Anforderungen. Wenn Sie DirectCast verwenden, muss der Typ bereits bekannt sein. Obwohl der Code ...
theString = DirectCast (theObject, String)
… Wird erfolgreich kompiliert, wenn theObject noch kein String ist, dann löst der Code eine Laufzeitausnahme aus.
TryCast ist noch restriktiver, da es bei "Wert" -Typen wie Integer überhaupt nicht funktioniert. (Zeichenfolge ist ein Referenztyp. Weitere Informationen zu Werttypen und Referenztypen finden Sie im ersten Artikel dieser Serie.) Dieser Code…
theInteger = TryCast (theObject, Integer)
... wird nicht einmal kompilieren.
TryCast ist nützlich, wenn Sie sich nicht sicher sind, mit welchem Objekttyp Sie arbeiten. Anstatt einen Fehler wie DirectCast auszulösen, gibt TryCast einfach Nothing zurück. Normalerweise wird nach der Ausführung von TryCast auf Nothing getestet.
Nur CType (und die anderen "Convert" -Operatoren wie CInt und CBool) konvertieren Typen, die keine Vererbungsbeziehung haben, z. B. eine Ganzzahl in einen String:
Dim theString As String = "1" Dim theInteger As Integer theInteger = CType (theString, Integer)
Dies funktioniert, weil CType "Hilfsfunktionen" verwendet, die nicht Teil der .NET CLR (Common Language Runtime) sind, um diese Konvertierungen durchzuführen.
Beachten Sie jedoch, dass CType auch eine Ausnahme auslöst, wenn theString nichts enthält, das in eine Ganzzahl konvertiert werden kann. Wenn die Möglichkeit besteht, dass der String keine Ganzzahl wie diese ist ...
Dim theString As String = "George"
… Dann arbeitet kein Casting-Operator. Selbst TryCast funktioniert nicht mit Integer, da es sich um einen Wertetyp handelt. In einem solchen Fall müssten Sie die Gültigkeitsprüfung verwenden, z. B. den Operator TypeOf, um Ihre Daten zu überprüfen, bevor Sie versuchen, sie zu übertragen.
In der Microsoft-Dokumentation für DirectCast wird speziell das Casting mit einem Objekttyp erwähnt, sodass ich dies in meinem ersten Leistungstest verwendet habe. Der Test beginnt auf der nächsten Seite!
Da DirectCast normalerweise einen Objekttyp verwendet, habe ich diesen bei meinem ersten Leistungstest verwendet. Um TryCast in den Test aufzunehmen, habe ich auch einen If-Block eingefügt, da fast alle Programme, die TryCast verwenden, einen haben. In diesem Fall wird es jedoch niemals ausgeführt.
Hier ist der Code, der alle drei vergleicht, wenn ein Objekt in einen String umgewandelt wird:
Dimmen Sie die Zeit als neue Stoppuhr () Dimmen Sie den String als Zeichenfolge Dimmen Sie das Objekt als Objekt = "Ein Objekt" Dimmen Sie die Iterationen als Ganzzahl = CInt (Iterations.Text) * 1000000 "DirectCast Testen Sie theTime.Start () Für i = 0 Für die Iterationen theString = DirectCast (theObject, String) Next theTime.Stop () DirectCastTime.Text = theTime.ElapsedMilliseconds.ToString "CType Test theTime.Restart () For i As Integer = 0 To theIterations theString = CType (theObject, String) Next theTime.Stop () CTypeTime.Text = theTime.ElapsedMilliseconds.ToString "TryCast Teste theTime.Restart () For i As Integer = 0 To theIterations theString = TryCast (theObject, String) Wenn theString nichts ist, dann MsgBox (" Dies sollte niemals angezeigt werden ") End If Next theTime.Stop () TryCastTime.Text = theTime.ElapsedMilliseconds.ToString
Dieser erste Test scheint zu zeigen, dass Microsoft genau richtig ist. Hier ist das Ergebnis. (Experimente mit einer größeren und kleineren Anzahl von Iterationen sowie wiederholte Tests unter verschiedenen Bedingungen zeigten keine signifikanten Unterschiede zu diesem Ergebnis.)
--------
Klicken Sie hier, um die Abbildung anzuzeigen
--------
DirectCast und TryCast waren bei 323 und 356 Millisekunden ähnlich, aber CType nahm bei 1018 Millisekunden mehr als dreimal so viel Zeit in Anspruch. Wenn Sie Referenztypen wie diese übertragen, zahlen Sie für die Flexibilität von CType in Bezug auf die Leistung.
Aber funktioniert das immer so? Das Microsoft-Beispiel auf der Seite für DirectCast ist hauptsächlich nützlich, um Ihnen zu sagen, was passiert Gewohnheit arbeiten mit DirectCast, nicht was wird. Hier ist das Microsoft-Beispiel:
Dim q As Object = 2.37 Dim i As Integer = CType (q, Integer) 'Die folgende Konvertierung schlägt zur Laufzeit fehl Dim j As Integer = DirectCast (q, Integer) Dim f As New System.Windows.Forms.Form Dim c As System.Windows.Forms.Control 'Die folgende Konvertierung ist erfolgreich. c = DirectCast (f, System.Windows.Forms.Control)
Mit anderen Worten, Sie kippen Verwenden Sie DirectCast (oder TryCast, obwohl sie es hier nicht erwähnen), um einen Object-Typ in einen Integer-Typ umzuwandeln, aber Sie können Verwenden Sie DirectCast, um einen Formulartyp in einen Steuerelementtyp umzuwandeln.
Lassen Sie uns die Leistung von Microsofts Beispiel überprüfen werden arbeite mit DirectCast. Verwenden Sie dieselbe oben gezeigte Codevorlage, um Folgendes zu ersetzen:
c = DirectCast (f, System.Windows.Forms.Control)
… In den Code zusammen mit ähnlichen Ersetzungen für CType und TryCast. Die Ergebnisse sind etwas überraschend.
--------
Klicken Sie hier, um die Abbildung anzuzeigen
--------
DirectCast war mit 145 Millisekunden die langsamste der drei Auswahlmöglichkeiten. CType ist mit 127 Millisekunden nur ein bisschen schneller, aber TryCast, einschließlich eines If-Blocks, ist mit 77 Millisekunden am schnellsten. Ich habe auch versucht, meine eigenen Objekte zu schreiben:
Klasse ParentClass… End Class Class ChildClass Übernimmt ParentClass… End Class
Ich habe ähnliche Ergebnisse erhalten. Es scheint, dass, wenn Sie sind nicht Wenn Sie einen Objekttyp auswählen, sind Sie besser dran nicht mit DirectCast.