Ternärer Operator VB vs C #: Warum löst nichts zu Null?
-
30-09-2019 - |
Frage
Ich drehe mich nur in dem Fuß und würde gerne wissen, ob es gab tatsächliche Gründe diese Situation möglich zu machen.
Und überhaupt, diese Frage kann für die Bequemlichkeit der zukünftigen Fuß Schützen bleiben.
Angenommen, wir einen Wert in vb.net haben:
Dim i as Integer?
Wir wollen einen Wert zuweisen, auf einer Bedingung basieren, und einen ternären Operator verwenden, weil es so ordentlich ist und Sachen:
i = If(condition(), Nothing, 42)
Das heißt, wenn eine Bedingung true
ist, verwendet die NULL-Zulässigkeit, andernfalls wird der Wert.
An welchem ??Punkt das Schießen stattfindet. Ohne ersichtlichen Grund entscheiden VB-Compiler, dass der gemeinsame Basistyp für Nothing
und Integer
ist Integer
, an welcher Stelle es still die Aussage übersetzt:
i = If(condition(), 0, 42)
Wenn Sie jetzt sind dies in C # tun:
i = (condition()) ? null : 42;
Sie würden sofort einen Compiler-Fehler erhalten, dass <null>
nicht gut mit int
mischt. Welches ist groß, wie mein Fuß gewesen wäre gesünder hatte ich diesmal den C # Weg ging. Und dafür zu kompilieren, müssen Sie explizit schreiben:
i = (condition()) ? null : (int?)42;
Nun, Sie können das gleiche tun in VB und nutzen Sie die richtige null-ness Sie erwarten:
i = If(condition(), Nothing, CType(42, Integer?))
Aber das mit dem Fuß Schuss an erster Stelle erfordert. Es gibt keinen Compiler-Fehler und es gibt keine Warnung. Das ist, mit Explicit On
und Strict On
.
Also meine Frage ist, warum?
Sollte ich dies als einen Compiler Fehler?
Oder kann jemand erklären, warum die Compiler auf diese Weise verhält?
Lösung
Das ist, weil VB Nothing
zu C # 's null
nicht direkt entspricht.
Zum Beispiel dieser Code in C # wird nicht kompiliert:
int i = null;
Aber das VB.Net Code funktioniert gut:
Dim i As Integer = Nothing
VB.Net der Nothing
ist eigentlich eine bessere Übereinstimmung für C # 's default(T)
Ausdruck.
Andere Tipps
Der ternäre Operator kann nur einen Typ zurück.
In C #, versucht er, eine Art auf null
und 42
, zu wählen. Nun, null
keinen Typ, so entscheidet sie, dass der Rückgabetyp des ternären Operator, dass der 42
ist; eine einfache alte int
. Dann wirft sie, weil Sie nicht null als plain old int
zurückkehren kann. Wenn Sie 42 als int?
zwingen, der ternäre Operator wird einen int?
zurückzukehren, so null
gültigen.
Nun, ich weiß nicht, VB, aber unter Angabe von der MSDN,
Assigning Nothing to a variable sets it to the default value for its declared type.
Welche, da VB bestimmt, dass der ternäre Operator eine int
zurückkehren (mit dem gleichen Prozess C # hat), ist Nothing
0
. Auch die 42
Nötigung eine int?
Umdrehung Nothing
in den Standardwert von int?
zu sein, die null
ist, wie erwartet.
Ich denke hat dies etwas mehr mit IF zu tun, als mit Nichts. Betrachten Sie diesen Code ein:
''# This raises an exception
Dim x As Integer?
x = If(True, Nothing, Nothing)
MessageBox.Show(x.Value)
''# As does
Dim x As Integer?
x = Nothing
MessageBox.Show(x.Value)
''# Changing one of the truthpart arguments of If is what seems to return the zero.
Dim x As Integer?
x = If(True, Nothing, 5)
MessageBox.Show(x.Value)
Warum es dies ich tut noch nicht wissen, wahrscheinlich eine Frage für das VB-Team. Ich glaube nicht, es hat mit dem Schlüsselwort Nothing oder Nullable zu tun.
Nothing
und null
ist nicht das Gleiche ... aus dem MSDN:
Zuweisen von nichts zu einem variablen Sätzen es auf den Standardwert für seinen deklarierten Typen.
Auch
Wenn Sie einen Werttyp in Expression liefern, gibt IsNothing immer False.
Beachten Sie, dass int? ein Nullable Type ist, aber es ist immer noch ein Werttyp, kein Referenztyp.
Versuchen Sie es Einstellung statt DbNull.Value
...
Nothing
In einer Reihe von Fällen Nothing
wird auf den Standardwert konvertiert werden. Um die Verwendung Nothing
auf die gleiche Weise null
verwenden würden Sie es auf den richtigen Nullable Type zu werfen brauchen.
Dim str As String
Dim int As Nullable(Of Integer) ' or use As Integer?
Dim reader As SqlDataReader
Dim colA As Integer = reader.GetOrdinal("colA")
Dim colB As Integer = reader.GetOrdinal("colB")
str = If(reader.IsDBNull(colA), DirectCast(Nothing, String), reader.GetString(colA))
int = If(reader.IsDBNull(colB), DirectCast(Nothing, Nullable(Of Integer)), reader.GetInt32(colB))
Dies geschieht, weil Integer kein Referenztyp ist. ‚Nichts‘ ist nur Arbeit für Referenztypen soll. Für Werttypen Nichts Zuordnung wird automatisch auf den Standardwert umgewandelt, die im Falle eines Integer 0 ist.
Dies ist eigentlich jetzt möglich, in VS2015 (am allerwenigsten) unter Verwendung von New Integer?
Bsp .:
Wenn (testInt> 0, testInt, New Integer?), Wo testInt vom Typ Integer ist?