Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Konvertierung ist der Prozess des Änderns eines Werts von einem Typ in einen anderen. Beispielsweise kann ein Typwert Integer in einen Typwert Doublekonvertiert werden, oder ein Typwert Derived kann in einen Typwert Basekonvertiert werden, vorausgesetzt, dass Base es sich um Klassen handelt Derived und Derived von Basedenen geerbt wird. Konvertierungen erfordern möglicherweise nicht, dass sich der Wert selbst ändert (wie im letzten Beispiel), oder sie erfordern erhebliche Änderungen in der Wertdarstellung (wie im vorherigen Beispiel).
Konvertierungen können entweder verbreitern oder verengt werden. Eine Erweiterungskonvertierung ist eine Konvertierung von einem Typ in einen anderen Typ, dessen Wertdomäne mindestens so groß ist, wenn nicht größer als die Wertdomäne des ursprünglichen Typs. Die Verbreiterungskonvertierungen sollten niemals fehlschlagen. Bei einer schmalen Konvertierung handelt es sich um eine Konvertierung von einem Typ in einen anderen Typ, dessen Wertdomäne entweder kleiner als die Wertdomäne des ursprünglichen Typs oder ausreichend nicht mit der Verbindung verbunden ist, die beim Konvertieren der Konvertierung (z. B. beim Konvertieren von Integer in String) erforderlich ist. Die Verengung von Konvertierungen, die zu Einem Verlust von Informationen führen können, kann fehlschlagen.
Die Identitätskonvertierung (d. h. eine Konvertierung von einem Typ in sich) und die Standardwertkonvertierung (d. h. eine Konvertierung von Nothing) werden für alle Typen definiert.
Implizite und explizite Konvertierungen
Konvertierungen können implizit oder explizit sein. Implizite Konvertierungen treten ohne spezielle Syntax auf. Im Folgenden sehen Sie ein Beispiel für die implizite Konvertierung eines Integer Werts in einen Long Wert:
Module Test
Sub Main()
Dim intValue As Integer = 123
Dim longValue As Long = intValue
Console.WriteLine(intValue & " = " & longValue)
End Sub
End Module
Explizite Konvertierungen erfordern dagegen Umwandlungsoperatoren. Wenn Sie versuchen, eine explizite Konvertierung für einen Wert ohne Umwandlungsoperator durchzuführen, tritt ein Kompilierungszeitfehler auf. Im folgenden Beispiel wird eine explizite Konvertierung verwendet, um einen Long Wert in einen Integer Wert zu konvertieren.
Module Test
Sub Main()
Dim longValue As Long = 134
Dim intValue As Integer = CInt(longValue)
Console.WriteLine(longValue & " = " & intValue)
End Sub
End Module
Der Satz impliziter Konvertierungen hängt von der Kompilierungsumgebung und der Option Strict Anweisung ab. Wenn strenge Semantik verwendet wird, können nur Verbreiterungskonvertierungen implizit auftreten. Wenn zulässige Semantik verwendet wird, können alle Verbreiterungs- und Eingrenzungskonvertierungen (mit anderen Worten alle Konvertierungen) implizit auftreten.
Boolesche Konvertierungen
Obwohl Boolean es sich nicht um einen numerischen Typ handelt, gibt es schmale Konvertierungen in und aus den numerischen Typen, als ob es sich um einen aufgezählten Typ handelt. Das Literal True wird in das Literal 255 für , 65535 for ByteUShort, 184467440737095516154294967295 for UInteger, und ULongin den Ausdruck -1 für SByte, Short, , , LongInteger, Decimal, , , und .DoubleSingle Das Literal False wird in das Literal 0konvertiert. Ein numerischer Nullwert wird in das Literal Falsekonvertiert. Alle anderen numerischen Werte werden in das Literal Truekonvertiert.
Es gibt eine schmale Konvertierung von Boolean in String, die in eine oder System.Boolean.FalseStringmehrere System.Boolean.TrueString Zeichenfolgen konvertiert wird. Es gibt auch eine Schmalungskonvertierung von String zu Boolean: Wenn die Zeichenfolge gleich TrueString oder FalseString (in der aktuellen Kultur, Groß-/Kleinschreibung ohne Berücksichtigung) ist, wird der entsprechende Wert verwendet. Andernfalls wird versucht, die Zeichenfolge als numerischen Typ zu analysieren (wenn möglich, andernfalls als Gleitkomma), und verwendet die oben genannten Regeln. Andernfalls wird die Zeichenfolge ausgelöst System.InvalidCastException.
Numerische Konvertierungen
Numerische Konvertierungen bestehen zwischen den Typen Byte, , SByte, UShort, Short, UInteger, , Integer, ULong, Long, Decimal, und Single , und , und Doublealle aufgezählten Typen. Beim Konvertieren werden aufgezählte Typen so behandelt, als wären sie ihre zugrunde liegenden Typen. Beim Konvertieren in einen Aufzählungstyp ist der Quellwert nicht erforderlich, um den im Aufzählungstyp definierten Wertesatz zu entsprechen. Beispiel:
Enum Values
One
Two
Three
End Enum
Module Test
Sub Main()
Dim x As Integer = 5
' OK, even though there is no enumerated value for 5.
Dim y As Values = CType(x, Values)
End Sub
End Module
Numerische Konvertierungen werden zur Laufzeit wie folgt verarbeitet:
Bei einer Konvertierung von einem numerischen Typ in einen breiteren numerischen Typ wird der Wert einfach in den breiteren Typ konvertiert. Konvertierungen von
UInteger,Integer,ULong, oderLongzuSingleoderDecimalDoublewerden auf den nächstenSingleoderDoubleWert gerundet. Obwohl diese Konvertierung zu einem Genauigkeitsverlust führen kann, wird sie niemals zu einem Verlust der Größe führen.Bei einer Konvertierung von einem integralen Typ in einen anderen integralen Typ oder von ,
Doubleoder vonSingle, oderDecimalzu einem integralen Typ hängt das Ergebnis davon ab, ob die Überlaufüberprüfung für ganze Zahlen aktiviert ist:Wenn der ganzzahlige Überlauf aktiviert wird:
Wenn es sich bei der Quelle um einen integralen Typ handelt, ist die Konvertierung erfolgreich, wenn sich das Quellargument innerhalb des Bereichs des Zieltyps befindet. Die Konvertierung löst eine
System.OverflowExceptionAusnahme aus, wenn sich das Quellargument außerhalb des Bereichs des Zieltyps befindet.Wenn die Quelle oder
DoubleDecimalder QuellwertSingleauf den nächsten integralen Wert aufgerundet wird und dieser integrale Wert das Ergebnis der Konvertierung wird. Wenn der Quellwert gleich zwei integralen Werten entspricht, wird der Wert auf den Wert gerundet, der eine gerade Zahl in der am wenigsten signifikanten Position aufweist. Wenn sich der resultierende integrale Wert außerhalb des Zieltyps befindet, wird eineSystem.OverflowExceptionAusnahme ausgelöst.
Wenn der ganzzahlige Überlauf nicht überprüft wird:
Wenn es sich bei der Quelle um einen integralen Typ handelt, ist die Konvertierung immer erfolgreich und besteht einfach darin, die wichtigsten Bits des Quellwerts zu verwerfen.
Wenn die Quelle ,
DoubleoderDecimal, die Konvertierung immer erfolgreich istSingleund einfach besteht aus dem Runden des Quellwerts auf den nächsten integralen Wert. Wenn der Quellwert gleich zwei integralen Werten entspricht, wird der Wert immer auf den Wert gerundet, der eine gerade Zahl in der am wenigsten signifikanten Position aufweist.
Bei einer Konvertierung von
Doublein " inSingle" wird derDoubleWert auf den nächstenSingleWert gerundet. Wenn derDoubleWert zu klein ist, um als einSingleWert darzustellen, wird das Ergebnis zu positiver Null oder negativer Null. Wenn derDoubleWert zu groß ist, um als einSingleWert darzustellen, wird das Ergebnis zu positiver Unendlichkeit oder negativer Unendlichkeit. Wenn derDoubleWert lautetNaN, ist das Ergebnis auchNaN.Bei einer Konvertierung von
SingleoderDoublein " inDecimal" wird der Quellwert in Darstellung konvertiertDecimalund bei Bedarf auf die nächste Zahl gerundet. Wenn der Quellwert zu klein ist, um als einDecimalObjekt darzustellen, wird das Ergebnis null. Wenn der QuellwertNaN, unendlich oder zu groß ist, um als EineDecimaldarzustellen, wird eineSystem.OverflowExceptionAusnahme ausgelöst.Bei einer Konvertierung von
Doublein " inSingle" wird derDoubleWert auf den nächstenSingleWert gerundet. Wenn derDoubleWert zu klein ist, um als einSingleWert darzustellen, wird das Ergebnis zu positiver Null oder negativer Null. Wenn derDoubleWert zu groß ist, um als einSingleWert darzustellen, wird das Ergebnis zu positiver Unendlichkeit oder negativer Unendlichkeit. Wenn derDoubleWert lautetNaN, ist das Ergebnis auchNaN.
Referenzkonvertierungen
Referenztypen können in einen Basistyp konvertiert werden und umgekehrt. Konvertierungen von einem Basistyp zu einem abgeleiteten Typ sind zur Laufzeit nur erfolgreich, wenn der zu konvertierende Wert ein NULL-Wert, der abgeleitete Typ selbst oder ein abgeleiteter Typ ist.
Klassen- und Schnittstellentypen können in einen beliebigen Schnittstellentyp und von jedem Schnittstellentyp umgegossen werden. Konvertierungen zwischen einem Typ und einem Schnittstellentyp sind zur Laufzeit nur erfolgreich, wenn die tatsächlich beteiligten Typen eine Vererbungs- oder Implementierungsbeziehung aufweisen. Da ein Schnittstellentyp immer eine Instanz eines Typs enthält, von Objectdem abgeleitet wird, kann ein Schnittstellentyp auch immer in und von diesen Objectumgeformt werden.
Hinweis: Es ist kein Fehler, eine NotInheritable Klassen in und von Schnittstellen zu konvertieren, die nicht implementiert werden, da Klassen, die COM-Klassen darstellen, Schnittstellenimplementierungen aufweisen, die bis zur Laufzeit nicht bekannt sind.
Wenn zur Laufzeit eine Verweiskonvertierung fehlschlägt, wird eine System.InvalidCastException Ausnahme ausgelöst.
Referenzabweichungskonvertierungen
Generische Schnittstellen oder Stellvertretungen verfügen möglicherweise über Variantentypparameter, die Konvertierungen zwischen kompatiblen Varianten des Typs ermöglichen. Daher wird zur Laufzeit eine Konvertierung von einem Klassentyp oder einem Schnittstellentyp in einen Schnittstellentyp ausgeführt, der mit einem Schnittstellentyp kompatibel ist, von dem er erbt oder implementiert wird. Ebenso können Stellvertretungstypen in variantenkompatible Delegattypen und aus diesen übertragen werden. Beispiel: Der Delegattyp
Delegate Function F(Of In A, Out R)(a As A) As R
würde eine Konvertierung von F(Of Object, Integer) zu F(Of String, Integer). Das heißt, eine Stellvertretung F , die Object sicher als Stellvertretung F verwendet werden kann, die akzeptiert String. Wenn der Delegat aufgerufen wird, erwartet die Zielmethode ein Objekt, und eine Zeichenfolge ist ein Objekt.
Ein generischer Delegat- oder Schnittstellentyp S(Of S1,...,Sn) soll mit einer generischen Schnittstelle oder einem Stellvertretungstyp T(Of T1,...,Tn) kompatibel sein, wenn:
SundTbeide aus demselben generischen TypU(Of U1,...,Un)erstellt werden.Für jeden Typparameter
Ux:Wenn der Typparameter ohne Varianz
Sxdeklariert wurde,Txmuss derselbe Typ sein.Wenn der Typparameter deklariert
Inwurde, muss es eine Erweiterungsidentität, eine Standard-, Verweis-, Array- oder Typparameterkonvertierung vonSxzuTx.Wenn der Typparameter deklariert
Outwurde, muss es eine Erweiterungsidentität, eine Standard-, Verweis-, Array- oder Typparameterkonvertierung vonTxzuSx.
Wenn die Klasse von einer Klasse in eine generische Schnittstelle mit Variantentypparametern konvertiert wird, wenn die Klasse mehr als eine variantkompatible Schnittstelle implementiert, ist die Konvertierung mehrdeutig, wenn keine Nicht-Variant-Konvertierung vorhanden ist. Beispiel:
Class Base
End Class
Class Derived1
Inherits Base
End Class
Class Derived2
Inherits Base
End Class
Class OneAndTwo
Implements IEnumerable(Of Derived1)
Implements IEnumerable(Of Derived2)
End Class
Class BaseAndOneAndTwo
Implements IEnumerable(Of Base)
Implements IEnumerable(Of Derived1)
Implements IEnumerable(Of Derived2)
End Class
Module Test
Sub Main()
' Error: conversion is ambiguous
Dim x As IEnumerable(Of Base) = New OneAndTwo()
' OK, will pick up the direct implementation of IEnumerable(Of Base)
Dim y as IEnumerable(Of Base) = New BaseAndOneAndTwo()
End Sub
End Module
Konvertierungen anonymer Stellvertretungen
Wenn ein ausdruck, der als Lambda-Methode klassifiziert wird, in einem Kontext, in dem kein Zieltyp vorhanden ist (z Dim x = Function(a As Integer, b As Integer) a + b. B. ), oder wenn der Zieltyp kein Delegattyp ist, ist der Typ des resultierenden Ausdrucks ein anonymer Delegattyp, der der Signatur der Lambda-Methode entspricht. Dieser anonyme Delegattyp weist eine Konvertierung in jeden kompatiblen Delegattyp auf: Ein kompatibler Delegattyp ist jeder Delegattyp, der mithilfe eines Delegaterstellungsausdrucks mit der Methode des anonymen Delegattyps Invoke als Parameter erstellt werden kann. Beispiel:
' Anonymous delegate type similar to Func(Of Object, Object, Object)
Dim x = Function(x, y) x + y
' OK because delegate type is compatible
Dim y As Func(Of Integer, Integer, Integer) = x
Beachten Sie, dass die Typen System.Delegate und System.MulticastDelegate nicht selbst Stellvertretungstypen gelten (auch wenn alle Stellvertretungstypen von ihnen erben). Beachten Sie außerdem, dass die Konvertierung von anonymem Delegattyp in einen kompatiblen Delegattyp keine Referenzkonvertierung ist.
Arraykonvertierungen
Neben den Konvertierungen, die auf Arrays definiert sind, aufgrund der Tatsache, dass sie Referenztypen sind, gibt es für Arrays mehrere spezielle Konvertierungen.
Bei zwei Typen und , wenn sie sowohl Bezugstypen A als auch Typparameter sind, die nicht als Werttypen bekannt sind, und wenn A ein Bezug, array oder Typparameter konvertiert Bwird, ist eine Konvertierung von einem Array vom Typ A in ein Array vom Typ B mit demselben Rang vorhanden.B Diese Beziehung wird als Arraykovarianz bezeichnet. Die Arraykovarianz bedeutet insbesondere, dass ein Element eines Arrays, dessen Elementtyp tatsächlich ein Element eines Arrays ist, dessen Elementtyp vorhanden istB, vorausgesetzt, dass sowohl Bezugstypen als auch BA Referenztypen sind und B eine Bezugskonvertierung oder Arraykonvertierung aufweisenA.A Im folgenden Beispiel bewirkt der zweite Aufruf einer F Ausnahme, dass eine System.ArrayTypeMismatchException Ausnahme ausgelöst wird, da der tatsächliche Elementtyp b lautet String, nicht Object:
Module Test
Sub F(ByRef x As Object)
End Sub
Sub Main()
Dim a(10) As Object
Dim b() As Object = New String(10) {}
F(a(0)) ' OK.
F(b(1)) ' Not allowed: System.ArrayTypeMismatchException.
End Sub
End Module
Aufgrund der Arraykovarianz enthalten Zuordnungen zu Elementen des Referenztyparrays eine Laufzeitüberprüfung, mit der sichergestellt wird, dass der dem Arrayelement zugewiesene Wert tatsächlich von einem zulässigen Typ ist.
Module Test
Sub Fill(array() As Object, index As Integer, count As Integer, _
value As Object)
Dim i As Integer
For i = index To (index + count) - 1
array(i) = value
Next i
End Sub
Sub Main()
Dim strings(100) As String
Fill(strings, 0, 101, "Undefined")
Fill(strings, 0, 10, Nothing)
Fill(strings, 91, 10, 0)
End Sub
End Module
In diesem Beispiel enthält die Zuordnung array(i) zur Methode Fill implizit eine Laufzeitüberprüfung, die sicherstellt, dass das objekt, auf das von der Variablen value verwiesen wird, entweder Nothing oder eine Instanz eines Typs ist, der mit dem tatsächlichen Elementtyp des Arrays arraykompatibel ist. Bei der Methode ist der erste Aufruf der Methode MainFill erfolgreich, der dritte Aufruf bewirkt jedoch, dass beim Ausführen der ersten Zuordnung array(i)eine System.ArrayTypeMismatchException Ausnahme ausgelöst wird. Die Ausnahme tritt auf, da ein Integer Array nicht gespeichert String werden kann.
Wenn einer der Arrayelementtypen ein Typparameter ist, dessen Typ sich als Werttyp zur Laufzeit herausstellt, wird eine System.InvalidCastException Ausnahme ausgelöst. Beispiel:
Module Test
Sub F(Of T As U, U)(x() As T)
Dim y() As U = x
End Sub
Sub Main()
' F will throw an exception because Integer() cannot be
' converted to Object()
F(New Integer() { 1, 2, 3 })
End Sub
End Module
Konvertierungen sind auch zwischen einem Array eines aufgezählten Typs und einem Array des zugrunde liegenden Typs des aufgezählten Typs oder einem Array eines anderen Aufzählungstyps mit demselben zugrunde liegenden Typ vorhanden, vorausgesetzt, die Arrays haben denselben Rang.
Enum Color As Byte
Red
Green
Blue
End Enum
Module Test
Sub Main()
Dim a(10) As Color
Dim b() As Integer
Dim c() As Byte
b = a ' Error: Integer is not the underlying type of Color
c = a ' OK
a = c ' OK
End Sub
End Module
In diesem Beispiel wird ein Array von Color einem Array des zugrunde liegenden Typs in und aus einem Array des ByteColorzugrunde liegenden Typs konvertiert. Die Konvertierung in ein Array von Integerist jedoch ein Fehler, da Integer es sich nicht um den zugrunde liegenden Typ von Color.
Ein Array vom Typ A() "Rang 1" hat auch eine Arraykonvertierung in die Sammlungsschnittstellentypen IList(Of B), IReadOnlyList(Of B), ICollection(Of B)IReadOnlyCollection(Of B) und IEnumerable(Of B) die in System.Collections.Generic, sofern eine der folgenden Bedingungen zutrifft:
-
AundBsind sowohl Bezugstypen als auch Typparameter, die nicht als Werttypen bekannt sind; undAweist eine Erweiterung des Bezugs, eines Arrays oder eines Typparameters aufB; oder -
AundBsind beide Aufzählungstypen desselben zugrunde liegenden Typs oder - einer von
AundBist ein aufgezählter Typ, und der andere ist der zugrunde liegende Typ.
Jedes Array vom Typ A mit einem beliebigen Rang weist auch eine Arraykonvertierung in die nicht generischen Sammlungsschnittstellentypen IListICollection auf und IEnumerable befindet sich in System.Collections.
Es ist möglich, die resultierenden Schnittstellen mithilfe For Eachoder durch direktes Aufrufen der GetEnumerator Methoden zu durchlaufen. Im Fall von Rang-1-Arrays, die generische oder nicht generische Formen von IList oder ICollection, es ist auch möglich, Elemente nach Index abzurufen. Im Fall von Rang-1-Arrays, die in generische oder nicht generische Formen IListkonvertiert werden, ist es auch möglich, Elemente nach Index festzulegen, vorbehaltlich der gleichen Laufzeit-Array-Kovarianzprüfungen wie oben beschrieben. Das Verhalten aller anderen Schnittstellenmethoden ist von der VB-Sprachspezifikation nicht definiert; es liegt bei der zugrunde liegenden Laufzeit.
Werttypkonvertierungen
Ein Werttypwert kann in einen seiner Basisverweistypen oder einen Schnittstellentyp konvertiert werden, der über einen Prozess implementiert wird, der als Boxing bezeichnet wird. Wenn ein Werttypwert eingefeldt wird, wird der Wert aus dem Speicherort kopiert, an dem er sich auf den .NET Framework-Heap befindet. Ein Verweis auf diesen Speicherort im Heap wird dann zurückgegeben und kann in einer Referenztypvariable gespeichert werden. Dieser Verweis wird auch als boxierte Instanz des Werttyps bezeichnet. Die boxed instance has the same semantics as a reference type instead of a value type.
Boxed value types can be converted back to their original value type through a process called unboxing. Wenn ein Feldwerttyp entboxt wird, wird der Wert aus dem Heap an einen variablen Speicherort kopiert. Ab diesem Zeitpunkt verhält es sich so, als ob es sich um einen Werttyp handelte. Beim Aufheben des Posteingangs eines Werttyps muss der Wert ein NULL-Wert oder eine Instanz des Werttyps sein. Andernfalls wird eine System.InvalidCastException Ausnahme ausgelöst. Wenn es sich bei dem Wert um eine Instanz eines Aufzählungstyps handelt, kann dieser Wert auch in den zugrunde liegenden Typ des aufgezählten Typs oder einen anderen Aufzählungstyp mit demselben zugrunde liegenden Typ entboxt werden. Ein Nullwert wird so behandelt, als wäre er das Literal Nothing.
Um Nullwertetypen gut zu unterstützen, wird der Werttyp System.Nullable(Of T) speziell beim Boxen und Aufheben des Posteingangs behandelt. Das Boxen eines Typs Nullable(Of T) führt zu einem Feldwert des TypsT, wenn die Eigenschaft des Werts HasValue oder ein Wert Nothing istTrue, wenn die Eigenschaft des Werts HasValue lautetFalse. Das Entpacken eines Typwerts T führt zu Nullable(Of T) einer Instanz Nullable(Of T) dessen Value Eigenschaft der Boxwert und dessen HasValue Eigenschaft ist True. Der Wert kann für jeden Wert Nothing aufgehoben Nullable(Of T) werden und führt zu einem Wert, dessen HasValue Eigenschaft lautetFalse.T Da boxed value types like reference types, it is possible to create multiple references to the same value. Für die Grundtypen und Enumerationstypen ist dies irrelevant, da Instanzen dieser Typen unveränderlich sind. Das heißt, es ist nicht möglich, eine boxierte Instanz dieser Typen zu ändern, daher ist es nicht möglich, die Tatsache zu beobachten, dass mehrere Verweise auf denselben Wert vorhanden sind.
Strukturen können dagegen änderbar sein, wenn auf ihre Instanzvariablen zugegriffen werden kann oder ob die Methoden oder Eigenschaften die Instanzvariablen ändern. Wenn ein Verweis auf eine Boxstruktur verwendet wird, um die Struktur zu ändern, werden alle Verweise auf die Boxstruktur die Änderung sehen. Da dieses Ergebnis unerwartet sein kann, wird beim Eingeben eines Werts Object , der von einem Speicherort in einen anderen Feldwerttypen eingegeben wird, automatisch auf dem Heap geklont, anstatt nur deren Verweise kopiert zu haben. Beispiel:
Class Class1
Public Value As Integer = 0
End Class
Structure Struct1
Public Value As Integer
End Structure
Module Test
Sub Main()
Dim val1 As Object = New Struct1()
Dim val2 As Object = val1
val2.Value = 123
Dim ref1 As Object = New Class1()
Dim ref2 As Object = ref1
ref2.Value = 123
Console.WriteLine("Values: " & val1.Value & ", " & val2.Value)
Console.WriteLine("Refs: " & ref1.Value & ", " & ref2.Value)
End Sub
End Module
Die Ausgabe des Programms ist:
Values: 0, 123
Refs: 123, 123
Die Zuordnung zum Feld der lokalen Variablen wirkt sich nicht auf das Feld der lokalen Variablen val2val1 aus, da beim Zuweisen val2des Felds Struct1 eine Kopie des Werts erstellt wurde. Im Gegensatz dazu wirkt sich die Zuordnung ref2.Value = 123 auf das Objekt aus, das sowohl als ref2 auch ref1 verweise.
Hinweis: Das Kopieren der Struktur erfolgt nicht für boxed structures typed, da System.ValueType es nicht möglich ist, verspätete Bindung von System.ValueType.
Es gibt eine Ausnahme von der Regel, die boxed value types wird bei der Zuordnung kopiert. Wenn ein Feldwerttypverweis innerhalb eines anderen Typs gespeichert wird, wird der innere Bezug nicht kopiert. Beispiel:
Structure Struct1
Public Value As Object
End Structure
Module Test
Sub Main()
Dim val1 As Struct1
Dim val2 As Struct1
val1.Value = New Struct1()
val1.Value.Value = 10
val2 = val1
val2.Value.Value = 123
Console.WriteLine("Values: " & val1.Value.Value & ", " & _
val2.Value.Value)
End Sub
End Module
Die Ausgabe des Programms ist:
Values: 123, 123
Dies liegt daran, dass der innere Feldwert nicht kopiert wird, wenn der Wert kopiert wird. Daher haben beide und val1.Valueval2.Value einen Verweis auf denselben Feldwerttyp.
Hinweis: Die Tatsache, dass inner boxed value types nicht kopiert werden, ist eine Einschränkung des .NET-Typsystems – um sicherzustellen, dass alle inneren Boxwerttypen kopiert wurden, wenn ein Wert des Typs Object kopiert wurde, unerschwinglich teuer wäre.
Wie zuvor beschrieben, können Boxwerttypen nur auf ihren ursprünglichen Typ entboxt werden. Boxed primitive Typen werden jedoch speziell behandelt, wenn sie eingegeben werden.Object Sie können in jeden anderen Grundtyp konvertiert werden, in den sie eine Konvertierung haben. Beispiel:
Module Test
Sub Main()
Dim o As Object = 5
Dim b As Byte = CByte(o) ' Legal
Console.WriteLine(b) ' Prints 5
End Sub
End Module
Normalerweise konnte der Boxwert Integer5 nicht in eine Byte Variable entboxt werden. Da Integer es sich jedoch um primitive Typen handelt Byte und eine Konvertierung aufweisen, ist die Konvertierung zulässig.
Beachten Sie, dass sich das Konvertieren eines Werttyps in eine Schnittstelle von einem generischen Argument unterscheidet, das auf eine Schnittstelle beschränkt ist. Beim Zugriff auf Schnittstellenmember für einen eingeschränkten Typparameter (oder aufrufende Methoden für Object) tritt das Boxen nicht auf, wenn ein Werttyp in eine Schnittstelle konvertiert wird und auf ein Schnittstellenmember zugegriffen wird. Angenommen, eine Schnittstelle ICounter enthält eine Methode Increment , die zum Ändern eines Werts verwendet werden kann. Wenn ICounter sie als Einschränkung verwendet wird, wird die Implementierung der Increment Methode mit einem Verweis auf die Variable aufgerufen, die Increment aufgerufen wurde, nicht eine Boxkopie:
Interface ICounter
Sub Increment()
ReadOnly Property Value() As Integer
End Interface
Structure Counter
Implements ICounter
Dim _value As Integer
Property Value() As Integer Implements ICounter.Value
Get
Return _value
End Get
End Property
Sub Increment() Implements ICounter.Increment
value += 1
End Sub
End Structure
Module Test
Sub Test(Of T As ICounter)(x As T)
Console.WriteLine(x.value)
x.Increment() ' Modify x
Console.WriteLine(x.value)
CType(x, ICounter).Increment() ' Modify boxed copy of x
Console.WriteLine(x.value)
End Sub
Sub Main()
Dim x As Counter
Test(x)
End Sub
End Module
Der erste Aufruf von Increment ändert den Wert in der Variablen x. Dies ist nicht gleichbedeutend mit dem zweiten Aufruf von Increment, der den Wert in einer geboxten Kopie von x ändert. Die Ausgabe des Programms ist also:
0
1
1
Konvertierungen des Nullwerttyps
Ein Werttyp T kann in und aus der nullablen Version des Typs konvertiert werden. T? Die Konvertierung von T? zu T löst eine System.InvalidOperationException Ausnahme aus, wenn der zu konvertierende Wert ist Nothing. Verfügt außerdem über eine Konvertierung in einen TypS, T? wenn T eine systeminterne Konvertierung vorhanden Sist. Und wenn S es sich um einen Werttyp handelt, sind die folgenden systeminternen Konvertierungen zwischen T? und S?:
Eine Konvertierung derselben Klassifizierung (Verengung oder Verbreiterung) von
T?zuS?.Eine Konvertierung derselben Klassifizierung (Verengung oder Verbreiterung) von
TzuS?.Eine schmale Konvertierung von
S?zuT.
Eine systeminterne Erweiterungskonvertierung ist beispielsweise von Integer? zu Long? einer systeminternen Erweiterungskonvertierung von Integer zu Long:
Dim i As Integer? = 10
Dim l As Long? = i
Beim Konvertieren von in T?S?, wenn der Wert des T? Werts ist Nothing, lautet der Wert von S?Nothing. Beim Konvertieren von in TS? oder T? in S, wenn der Wert von T? oder S? ist Nothing, wird eine System.InvalidCastException Ausnahme ausgelöst.
Aufgrund des Verhaltens des zugrunde liegenden Typs System.Nullable(Of T), wenn ein Nullwerttyp T? boxt, ist das Ergebnis ein Boxwert vom Typ T, nicht ein Boxwert vom Typ T?. Und umgekehrt wird der Wert beim Entpacken in einen Null-Wertetyp T?umbrochen System.Nullable(Of T)und Nothing wird in einen Nullwert des Typs T?entboxt. Beispiel:
Dim i1? As Integer = Nothing
Dim o1 As Object = i1
Console.WriteLine(o1 Is Nothing) ' Will print True
o1 = 10
i1 = CType(o1, Integer?)
Console.WriteLine(i1) ' Will print 10
Ein Nebeneffekt dieses Verhaltens besteht darin, dass ein Nullwerttyp T? alle Schnittstellen Timplementiert, da beim Konvertieren eines Werttyps in eine Schnittstelle der Typ ein Boxen erforderlich ist. Daher T? ist das Konvertierbar für alle Schnittstellen, T die konvertierbar sind. Es ist jedoch wichtig zu beachten, dass ein nullabler Werttyp T? nicht tatsächlich die Schnittstellen T für die generische Einschränkungsprüfung oder Reflexion implementiert. Beispiel:
Interface I1
End Interface
Structure T1
Implements I1
...
End Structure
Module Test
Sub M1(Of T As I1)(ByVal x As T)
End Sub
Sub Main()
Dim x? As T1 = Nothing
Dim y As I1 = x ' Valid
M1(x) ' Error: x? does not satisfy I1 constraint
End Sub
End Module
Zeichenfolgenkonvertierungen
Konvertieren Char in String Ergebnisse in eine Zeichenfolge, deren erstes Zeichen der Zeichenwert ist. Das Konvertieren String in Char Ergebnisse in ein Zeichen, dessen Wert das erste Zeichen der Zeichenfolge ist. Das Konvertieren eines Arrays in CharString Ergebnisse in eine Zeichenfolge, deren Zeichen die Elemente des Arrays sind. Konvertieren String in ein Array von Char Ergebnissen in ein Array von Zeichen, deren Elemente die Zeichen der Zeichenfolge sind.
Die genauen Konvertierungen zwischen und , , , , UShort, Short, , UInteger, Integer, , LongULong, DateDecimalDoubleSingleund umgekehrt, sind über den Umfang dieser Spezifikation hinaus und sind implementierungsabhängig mit Ausnahme eines Details. SByteByteBooleanString Zeichenfolgenkonvertierungen berücksichtigen immer die aktuelle Kultur der Laufzeitumgebung. Daher müssen sie zur Laufzeit ausgeführt werden.
Erweiterungskonvertierungen
Verbreiterungskonvertierungen überlaufen niemals überlaufen, können aber zu einem Genauigkeitsverlust führen. Bei den folgenden Konvertierungen handelt es sich um Erweiterungskonvertierungen:
Identitäts-/Standardkonvertierungen
Von einem Typ zu sich selbst.
Von einem anonymen Delegattyp, der für eine Lambda-Methode neu klassifiziert wird, auf jeden Delegattyp mit einer identischen Signatur.
Vom Literal
Nothingzu einem Typ.
Numerische Konvertierungen
Von
BytebisUShort,Short,UInteger,Integer,ULong, ,Long, ,DecimaloderSingleDouble.Von
SByteinShort,Integer,Long,Decimal,SingleoderDouble.Von
UShortinUInteger,Integer,ULong,Long,Decimal,SingleoderDouble.Von
ShortbisInteger,Long, ,DecimaloderDoubleSingle.Von
UIntegerinULong,Long,Decimal,SingleoderDouble.Von
IntegerbisLong,Decimal,SingleoderDouble.Von
ULonginDecimal,SingleoderDouble.Von
Longbis ,SingleDecimaloderDouble.Von
DecimalinSingleoderDouble.Von
SinglebisDouble.Vom Literal
0zu einem Aufzählungstyp. (Hinweis. Die Konvertierung von0einem aufgezählten Typ wird erweitert, um Testkennzeichnungen zu vereinfachen. Wenn es sich zValues. B. um einen Aufzählungstyp mit einem WertOnehandelt, können Sie eine Variablevvom TypValuestesten, indem(v And Values.One) = 0Sie ".)Von einem Aufzählungstyp auf den zugrunde liegenden numerischen Typ oder auf einen numerischen Typ, in den der zugrunde liegende numerische Typ eine Erweiterungskonvertierung aufweist.
Von einem konstanten Ausdruck vom Typ
ULong, , ,UInteger,Integer,UShort,Short, oderByteSBytezu einem schmaleren Typ, vorausgesetzt, der Wert des Konstantenausdrucks befindet sich innerhalb des Bereichs des ZieltypsLong. (Hinweis. Konvertierungen vonUIntegeroderIntegerinSingleoderULongLonginSingleoder zu oderDoublezu oderSingleDecimalDoublekönnen zu einem Verlust der Genauigkeit führen, aber niemals zu einem Verlust der Größe führen. Die anderen erweiternden numerischen Konvertierungen verlieren niemals Informationen.)
Referenzkonvertierungen
Von einem Verweistyp zu einem Basistyp.
Von einem Verweistyp auf einen Schnittstellentyp, vorausgesetzt, der Typ implementiert die Schnittstelle oder eine variantekompatible Schnittstelle.
Von einem Schnittstellentyp zu
Object.Von einem Schnittstellentyp zu einem variantenkompatiblen Schnittstellentyp.
Von einem Delegattyp zu einem variantenkompatiblen Delegattyp. (Hinweis. Viele andere Verweiskonvertierungen werden durch diese Regeln impliziert. Anonyme Stellvertretungen sind z. B. Referenztypen, die von
System.MulticastDelegate;Arraytypen erbenSystem.Array; anonyme Typen sind Referenztypen, die vonSystem.Object.)
Konvertierungen anonymer Stellvertretungen
- Von einem anonymen Delegattyp, der für eine Lambda-Methode neu klassifiziert wird, in einen größeren Delegattyp.
Arraykonvertierungen
Von einem Arraytyp mit einem Elementtyp
SSebis zu einem Arraytyp mit einem ElementtypTTe, vorausgesetzt, alle folgenden Werte sind wahr:SundTunterscheiden sich nur im Elementtyp.Beide
SesindTeBezugstypen oder Typparameter, die als Verweistyp bekannt sind.Es ist eine Erweiterung des Verweises, eines Arrays oder einer Typparameterkonvertierung vorhanden.
SeTe
Von einem Arraytyp
Smit einem AufzählungselementtypSezu einem Arraytyp mit einem ElementtypTTe, vorausgesetzt, alle folgenden Sind wahr:SundTunterscheiden sich nur im Elementtyp.Teist der zugrunde liegende Typ vonSe.
Von einem Arraytyp
Sder Rangfolge 1 mit einem aufgezählten ElementtypSe, bisSystem.Collections.Generic.IList(Of Te), ,IReadOnlyList(Of Te), ,ICollection(Of Te),IReadOnlyCollection(Of Te)undIEnumerable(Of Te), vorausgesetzt, einer der folgenden Werte ist wahr:Beide
SesindTeBezugstypen oder Typparameter, die als Bezugstyp bekannt sind, und eine Erweiterung des Bezugs, eines Arrays oder einer Typparameterkonvertierung besteht vonSezuTe; oderTeist der zugrunde liegende Typ vonSe; oderTeist identisch mitSe
Werttypkonvertierungen
Von einem Werttyp zu einem Basistyp.
Von einem Werttyp zu einem Schnittstellentyp, den der Typ implementiert.
Konvertierungen des Nullwerttyps
Von einem Typ
Tzum TypT?.Von einem Typ
T?zu einem TypS?, wobei eine Erweiterung von dem TypTin den TypSvorhanden ist.Von einem Typ
Tzu einem TypS?, wobei eine Erweiterung von dem TypTin den TypSvorhanden ist.Von einem Typ
T?zu einem Schnittstellentyp, den der TypTimplementiert.
Zeichenfolgenkonvertierungen
Von
CharbisString.Von
Char()bisString.
Typparameterkonvertierungen
Von einem Typparameter in
Object.Von einem Typparameter zu einer Schnittstellentypeinschränkung oder einer beliebigen Schnittstellenvariante, die mit einer Schnittstellentypeinschränkung kompatibel ist.
Von einem Typparameter zu einer Schnittstelle, die von einer Klasseneinschränkung implementiert wird.
Von einem Typparameter zu einer Schnittstellenvariante, die mit einer Schnittstelle kompatibel ist, die von einer Klasseneinschränkung implementiert wird.
Von einem Typparameter zu einer Klasseneinschränkung oder einem Basistyp der Klasseneinschränkung.
Von einem Typparameter
Tzu einer TypparametereinschränkungTxoder etwasTxhat eine Erweiterungskonvertierung.
Eingrenzungskonvertierungen
Schmale Konvertierungen sind Konvertierungen, die nicht immer erfolgreich sein können, Konvertierungen, die bekanntermaßen Informationen verlieren, und Konvertierungen in Domänen von Typen, die ausreichend unterschiedlich sind, um eine schmale Schreibweise zu erzielen. Die folgenden Konvertierungen werden als schmale Konvertierungen klassifiziert:
Boolesche Konvertierungen
Von
BooleanzuByte,SByte,UShort,Short,UInteger, ,Integer,ULong,LongDecimal, , , oderSingleDouble.Von
Byte, ,SByte,UShort,Short,IntegerUInteger, ,ULong,DecimalLong, ,SingleoderDoublenachBoolean.
Numerische Konvertierungen
Von
BytebisSByte.Von
SByteinByte,UShort,UIntegeroderULong.Von
UShortinByte,SByteoderShort.Von
ShortinByte,SByte,UShort,UIntegeroderULong.Von
UIntegerinByte,SByte,UShort,ShortoderInteger.Von
IntegerinByte,SByte,UShort,Short,UIntegeroderULong.Von
ULonginByte,SByte,UShort,Short,UInteger,IntegeroderLong.Von
LonginByte,SByte,UShort,Short,UInteger,IntegeroderULong.Von
DecimalinByte,SByte,UShort,Short,UInteger,Integer,ULongoderLong.Von
SinglebisByte,SByte,UShort,Short,UInteger, ,Integer, ,ULongoderLongDecimal.Von
DoublezuByte,SByte,UShort,Short,UInteger, ,Integer, ,ULong,Long, , oderDecimalSingle.Von einem numerischen Typ zu einem Aufzählungstyp.
Von einem Aufzählungstyp zu einem numerischen Typ weist sein zugrunde liegender numerischer Typ eine schmale Konvertierung auf.
Von einem Aufzählungstyp zu einem anderen Aufzählungstyp.
Referenzkonvertierungen
Von einem Verweistyp zu einem abgeleiteten Typ.
Von einem Klassentyp zu einem Schnittstellentyp, vorausgesetzt, der Klassentyp implementiert nicht den Schnittstellentyp oder eine schnittstellentypkompatible Variante.
Von einem Schnittstellentyp zu einem Klassentyp.
Von einem Schnittstellentyp zu einem anderen Schnittstellentyp, vorausgesetzt, es gibt keine Vererbungsbeziehung zwischen den beiden Typen und vorausgesetzt, sie sind nicht variantkompatibel.
Konvertierungen anonymer Stellvertretungen
- Von einem anonymen Delegattyp, der für eine Lambda-Methode neu klassifiziert wird, in einen schmaleren Delegattyp.
Arraykonvertierungen
Von einem Arraytyp mit einem Elementtyp
SSebis zu einem Arraytyp mit einem ElementtypTeT, vorausgesetzt, dass alle folgenden Werte zutreffen:-
SundTunterscheiden sich nur im Elementtyp. - Beide
SesindTeBezugstypen oder Typparameter, die nicht als Werttypen bekannt sind. - Ein schmaler Bezug, ein Array oder eine Typparameterkonvertierung ist von
SezuTe.
-
Von einem Arraytyp mit einem Elementtyp
SeSbis zu einem Arraytyp mit einem aufgezählten ElementtypTTe, vorausgesetzt, alle folgenden Sind wahr:-
SundTunterscheiden sich nur im Elementtyp. -
Seist der zugrunde liegende Typ oderTebeide enumerierten Typen, die denselben zugrunde liegenden Typ aufweisen.
-
Von einem Arraytyp
Sder Rangfolge 1 mit einem aufgezählten ElementtypSe, bisIList(Of Te),IReadOnlyList(Of Te), ,ICollection(Of Te)IReadOnlyCollection(Of Te)undIEnumerable(Of Te), vorausgesetzt, einer der folgenden Werte ist wahr:- Beide
SesindTeBezugstypen oder Typparameter, die als Bezugstyp bekannt sind, und eine schmale Bezugs-, Array- oder Typparameterkonvertierung ist vonSezuTe; oder -
Seist der zugrunde liegende Typ oderTebeide enumerierten Typen, die denselben zugrunde liegenden Typ aufweisen.
- Beide
Werttypkonvertierungen
Von einem Verweistyp bis zu einem abgeleiteten Werttyp.
Von einem Schnittstellentyp zu einem Werttyp, vorausgesetzt, der Werttyp implementiert den Schnittstellentyp.
Konvertierungen des Nullwerttyps
Von einem Typ
T?zu einem TypT.Von einem Typ
T?zu einem TypS?, wobei eine schmale Konvertierung vom TypTin den TypSvorhanden ist.Von einem Typ
Tzu einem TypS?, wobei eine schmale Konvertierung vom TypTin den TypSvorhanden ist.Von einem Typ
S?zu einem TypT, wobei eine Konvertierung vom TypSin den TypTvorhanden ist.
Zeichenfolgenkonvertierungen
Von
StringbisChar.Von
StringbisChar().Von
StringundBooleanvonBooleanbis zuString.Konvertierungen zwischen
StringundByte,SByte,UShort, ,UIntegerShort, ,Integer, ,ULong,Long,Decimal, oderSingleDouble.Von
StringundDatevonDatebis zuString.
Typparameterkonvertierungen
Von
Objectzu einem Typparameter.Von einem Typparameter zu einem Schnittstellentyp, vorausgesetzt, der Typparameter ist nicht auf diese Schnittstelle beschränkt oder auf eine Klasse beschränkt, die diese Schnittstelle implementiert.
Von einem Schnittstellentyp zu einem Typparameter.
Von einem Typparameter zu einem abgeleiteten Typ einer Klasseneinschränkung.
Von einem Typparameter
Tzu einer TypparametereinschränkungTxhat eine Schmalungskonvertierung.
Typparameterkonvertierungen
Die Konvertierungen von Typparametern werden durch die Einschränkungen bestimmt( falls vorhanden), die sie enthalten. Ein Typparameter T kann immer in sich, in und von und von Objectjedem Beliebigen Schnittstellentyp konvertiert werden. Beachten Sie, dass es sich bei dem Typ T bei der Laufzeit um einen Werttyp handelt, die Konvertierung von TObject oder einem Schnittstellentyp eine Boxkonvertierung und konvertierung von Object oder einem Schnittstellentyp T ist eine Unboxing-Konvertierung. Ein Typparameter mit einer Klasseneinschränkung C definiert zusätzliche Konvertierungen vom Typparameter in C die Basisklassen und umgekehrt. Ein Typparameter T mit einer Typparametereinschränkung Tx definiert eine Konvertierung in Tx und alle Tx Konvertierungen.
Ein Array, dessen Elementtyp ein Typparameter mit einer Schnittstelleneinschränkung I ist, weist dieselben kovarianten Arraykonvertierungen wie ein Array auf, dessen Elementtyp festgelegt ist I, vorausgesetzt, der Typparameter verfügt auch über eine Class Einschränkung oder Klasseneinschränkung (da nur Referenzarrayelementtypen kovariant sein können). Ein Array, dessen Elementtyp ein Typparameter mit einer Klasseneinschränkung C ist, weist die gleichen kovarianten Arraykonvertierungen wie ein Array auf, dessen Elementtyp lautet C.
Die oben genannten Konvertierungsregeln lassen keine Konvertierungen von nicht eingeschränkten Typparametern in Nicht-Schnittstellentypen zu, was überraschend sein kann. Der Grund dafür ist, Verwirrung über die Semantik solcher Konvertierungen zu vermeiden. Betrachten Sie beispielsweise die folgende Deklaration:
Class X(Of T)
Public Shared Function F(t As T) As Long
Return CLng(t) ' Error, explicit conversion not permitted
End Function
End Class
Wenn die Umwandlung von T "to Integer " zulässig wäre, könnte man leicht erwarten, dass X(Of Integer).F(7) dies zurückgegeben 7Lwürde. Dies wäre jedoch nicht der Fehler, da numerische Konvertierungen nur berücksichtigt werden, wenn die Typen zur Kompilierungszeit als numerisch bekannt sind. Um die Semantik klar zu machen, muss stattdessen das obige Beispiel geschrieben werden:
Class X(Of T)
Public Shared Function F(t As T) As Long
Return CLng(CObj(t)) ' OK, conversions permitted
End Function
End Class
User-Defined Konvertierungen
Systeminterne Konvertierungen sind Konvertierungen , die von der Sprache definiert werden (d. h. in dieser Spezifikation aufgeführt), während benutzerdefinierte Konvertierungen durch Überladung des CType Operators definiert werden. Wenn beim Konvertieren zwischen Typen keine systeminternen Konvertierungen anwendbar sind, werden benutzerdefinierte Konvertierungen berücksichtigt. Wenn eine benutzerdefinierte Konvertierung vorhanden ist, die für die Quell- und Zieltypen spezifisch ist, wird die benutzerdefinierte Konvertierung verwendet. Andernfalls ergibt sich ein Kompilierungszeitfehler. Die spezifischste Konvertierung ist der Operand, dessen Operand dem Quelltyp am nächsten kommt und dessen Ergebnistyp dem Zieltyp am nächsten kommt. Bei der Bestimmung der zu verwendenden benutzerdefinierten Konvertierung wird die spezifische Erweiterungskonvertierung verwendet; Wenn keine Erweiterungskonvertierung spezifisch ist, wird die spezifische Schmalungskonvertierung verwendet. Wenn keine spezifische Einschränkungskonvertierung vorhanden ist, ist die Konvertierung nicht definiert, und ein Kompilierungszeitfehler tritt auf.
In den folgenden Abschnitten wird beschrieben, wie die spezifischen Konvertierungen bestimmt werden. Sie verwenden die folgenden Begriffe:
Wenn eine systeminterne Erweiterungskonvertierung von einem Typ A zu einem Typ Bvorhanden ist und weder AB Schnittstellen noch Schnittstellen sind, A wird sie vonBund BumfasstA.
Der umfassendste Typ in einer Gruppe von Typen ist der einzige Typ, der alle anderen Typen in der Gruppe umfasst. Wenn kein einzelner Typ alle anderen Typen umfasst, weist der Satz keinen umfassendsten Typ auf. Intuitiv gesehen ist der umfassendste Typ der Gruppe der "größte" Typ - der einen Typ, in den jeder der anderen Typen durch eine Erweiterungskonvertierung konvertiert werden kann.
Der umfassendste Typ in einer Gruppe von Typen ist der typ, der von allen anderen Typen in der Gruppe umfasst wird. Wenn kein einzelner Typ von allen anderen Typen umfasst, hat der Satz keinen am meisten eingeschlossenen Typ. Intuitiv gesehen ist der am meisten eingeschlossene Typ der "kleinste" Typ in der Gruppe - der eine Typ, der durch eine schmale Konvertierung in jeden der anderen Typen konvertiert werden kann.
Beim Sammeln der benutzerdefinierten Konvertierungen für einen Typ T?werden stattdessen die benutzerdefinierten Konvertierungsoperatoren verwendet, die von T ihnen definiert werden. Wenn der Typ, in den konvertiert wird, auch ein Nullwerttyp ist, werden alle Tbenutzerdefinierten Konvertierungsoperatoren, die nur nicht nullable Werttypen umfassen, aufgehoben. Ein Konvertierungsoperator von T zu "In" wird aufgehoben, um eine Konvertierung von T? zu S? zu sein, und wird bei Bedarf ausgewertet, indem T?Ter in , falls erforderlich, den benutzerdefinierten Konvertierungsoperator TS auswertet und dann in , falls erforderlich, konvertiert.SS?S Wenn der zu konvertierende NothingWert jedoch ist, wird ein aufgehobener Konvertierungsoperator direkt in einen Wert vom Nothing Typ "As S?" konvertiert. Beispiel:
Structure S
...
End Structure
Structure T
Public Shared Widening Operator CType(ByVal v As T) As S
...
End Operator
End Structure
Module Test
Sub Main()
Dim x As T?
Dim y As S?
y = x ' Legal: y is still null
x = New T()
y = x ' Legal: Converts from T to S
End Sub
End Module
Bei der Auflösung von Konvertierungen werden benutzerdefinierte Konvertierungsoperatoren immer gegenüber aufgehobenen Konvertierungsoperatoren bevorzugt. Beispiel:
Structure S
...
End Structure
Structure T
Public Shared Widening Operator CType(ByVal v As T) As S
...
End Operator
Public Shared Widening Operator CType(ByVal v As T?) As S?
...
End Operator
End Structure
Module Test
Sub Main()
Dim x As T?
Dim y As S?
y = x ' Calls user-defined conversion, not lifted conversion
End Sub
End Module
Zur Laufzeit kann die Auswertung einer benutzerdefinierten Konvertierung bis zu drei Schritte umfassen:
Zunächst wird der Wert aus dem Quelltyp mithilfe einer systeminternen Konvertierung in den Operandentyp konvertiert.
Anschließend wird die benutzerdefinierte Konvertierung aufgerufen.
Schließlich wird das Ergebnis der benutzerdefinierten Konvertierung bei Bedarf mithilfe einer systeminternen Konvertierung in den Zieltyp konvertiert.
Es ist wichtig zu beachten, dass die Auswertung einer benutzerdefinierten Konvertierung niemals mehr als einen benutzerdefinierten Konvertierungsoperator umfasst.
Die spezifischste Verbreiterungskonvertierung
Die Ermittlung des spezifisch benutzerdefinierten Erweiterungskonvertierungsoperators zwischen zwei Typen erfolgt mithilfe der folgenden Schritte:
Zunächst werden alle Kandidatenkonvertierungsoperatoren gesammelt. Die Kandidatenkonvertierungsoperatoren sind alle benutzerdefinierten Verbreiterungsoperatoren im Quelltyp und alle benutzerdefinierten Erweiterungskonvertierungsoperatoren im Zieltyp.
Anschließend werden alle nicht anwendbaren Konvertierungsoperatoren aus der Gruppe entfernt. Ein Konvertierungsoperator gilt für einen Quelltyp und Zieltyp, wenn ein systeminterner Erweiterungskonvertierungsoperator vom Quelltyp auf den Operandentyp vorhanden ist und ein systeminterner Verbreiterungskonvertierungsoperator vom Ergebnis des Operators auf den Zieltyp vorhanden ist. Wenn keine anwendbaren Konvertierungsoperatoren vorhanden sind, gibt es keine spezifische Erweiterungskonvertierung.
Anschließend wird der spezifischste Quelltyp der entsprechenden Konvertierungsoperatoren bestimmt:
Wenn eine der Konvertierungsoperatoren direkt vom Quelltyp konvertiert wird, ist der Quelltyp der spezifischste Quelltyp.
Andernfalls ist der spezifischste Quelltyp der am meisten eingeschlossene Typ in der kombinierten Gruppe von Quelltypen der Konvertierungsoperatoren. Wenn kein umfassendster Typ gefunden werden kann, gibt es keine spezifische Erweiterungskonvertierung.
Anschließend wird der spezifischste Zieltyp der anwendbaren Konvertierungsoperatoren bestimmt:
Wenn eine der Konvertierungsoperatoren direkt in den Zieltyp konvertiert wird, ist der Zieltyp der spezifischste Zieltyp.
Andernfalls ist der spezifischste Zieltyp der umfassendste Typ in der kombinierten Gruppe von Zieltypen der Konvertierungsoperatoren. Wenn kein umfassendster Typ gefunden werden kann, gibt es keine spezifische Erweiterungskonvertierung.
Wenn dann genau ein Konvertierungsoperator vom spezifischsten Quelltyp in den spezifischsten Zieltyp konvertiert wird, ist dies der spezifischste Konvertierungsoperator. Wenn mehr als ein solcher Operator vorhanden ist, gibt es keine spezifische Erweiterungskonvertierung.
Die spezifischste Verengungskonvertierung
Die Ermittlung des spezifischen benutzerdefinierten Verengungsoperators zwischen zwei Typen erfolgt mithilfe der folgenden Schritte:
Zunächst werden alle Kandidatenkonvertierungsoperatoren gesammelt. Die Kandidatenkonvertierungsoperatoren sind alle benutzerdefinierten Konvertierungsoperatoren im Quelltyp und alle benutzerdefinierten Konvertierungsoperatoren im Zieltyp.
Anschließend werden alle nicht anwendbaren Konvertierungsoperatoren aus der Gruppe entfernt. Ein Konvertierungsoperator gilt für einen Quelltyp und Zieltyp, wenn ein systeminterner Konvertierungsoperator vom Quelltyp in den Operandentyp vorhanden ist und ein systeminterner Konvertierungsoperator vom Ergebnis des Operators in den Zieltyp vorhanden ist. Wenn keine anwendbaren Konvertierungsoperatoren vorhanden sind, gibt es keine spezifische Schmalungskonvertierung.
Anschließend wird der spezifischste Quelltyp der entsprechenden Konvertierungsoperatoren bestimmt:
Wenn eine der Konvertierungsoperatoren direkt vom Quelltyp konvertiert wird, ist der Quelltyp der spezifischste Quelltyp.
Andernfalls, wenn einer der Konvertierungsoperatoren aus Typen konvertiert wird, die den Quelltyp umfassen, ist der spezifischste Quelltyp der am meisten eingeschlossene Typ in der kombinierten Gruppe von Quelltypen dieser Konvertierungsoperatoren. Wenn kein umfassendster Typ gefunden werden kann, gibt es keine spezifische Verengungskonvertierung.
Andernfalls ist der spezifischste Quelltyp der umfassendste Typ in der kombinierten Gruppe von Quelltypen der Konvertierungsoperatoren. Wenn kein umfassendster Typ gefunden werden kann, gibt es keine spezifische Verengungskonvertierung.
Anschließend wird der spezifischste Zieltyp der anwendbaren Konvertierungsoperatoren bestimmt:
Wenn eine der Konvertierungsoperatoren direkt in den Zieltyp konvertiert wird, ist der Zieltyp der spezifischste Zieltyp.
Andernfalls, wenn eines der Konvertierungsoperatoren in Typen konvertiert wird, die vom Zieltyp eingeschlossen sind, ist der spezifischste Zieltyp der am meisten umfassende Typ in der kombinierten Gruppe von Quelltypen dieser Konvertierungsoperatoren. Wenn kein umfassendster Typ gefunden werden kann, gibt es keine spezifische Verengungskonvertierung.
Andernfalls ist der spezifischste Zieltyp der am meisten eingeschlossene Typ in der kombinierten Gruppe von Zieltypen der Konvertierungsoperatoren. Wenn kein umfassendster Typ gefunden werden kann, gibt es keine spezifische Verengungskonvertierung.
Wenn dann genau ein Konvertierungsoperator vom spezifischsten Quelltyp in den spezifischsten Zieltyp konvertiert wird, ist dies der spezifischste Konvertierungsoperator. Wenn mehr als ein solcher Operator vorhanden ist, gibt es keine spezifische Verengungskonvertierung.
Native Konvertierungen
Mehrere der Konvertierungen werden als systemeigene Konvertierungen klassifiziert, da sie von .NET Framework nativ unterstützt werden. Diese Konvertierungen sind solche, die durch die Verwendung der DirectCast Operatoren und TryCast Konvertierungsoperatoren sowie andere spezielle Verhaltensweisen optimiert werden können. Die als systemeigenen Konvertierungen klassifizierten Konvertierungen sind: Identitätskonvertierungen, Standardkonvertierungen, Referenzkonvertierungen, Arraykonvertierungen, Werttypkonvertierungen und Typparameterkonvertierungen.
Dominanter Typ
Angesichts einer Reihe von Typen ist es häufig erforderlich, in Situationen wie typinferenz, um den dominanten Typ des Satzes zu bestimmen. Der dominante Typ einer Gruppe von Typen wird bestimmt, indem zuerst alle Typen entfernt werden, in die mindestens ein anderer Typ keine implizite Konvertierung aufweist. Wenn an diesem Punkt keine Typen vorhanden sind, gibt es keinen dominanten Typ. Der dominante Typ wird dann am meisten von den verbleibenden Typen erfasst. Wenn mehr als ein Typ vorhanden ist, der am meisten umfasst ist, gibt es keinen dominanten Typ.
Visual Basic language spec