Pregunta

acabo de pegarme un tiro en el pie y me gustaría saber si hay razones reales para hacer posible esta situación.
Y de todos modos, esta pregunta puede permanecer para la comodidad de los tiradores del pie futuro.


Supongamos que tenemos un valor anulable en vb.net:

Dim i as Integer?

Queremos asignar un valor a la misma, basándose en una condición, y el uso de un operador ternario, porque es muy limpio y esas cosas:

i = If(condition(), Nothing, 42)

Es decir, si una condición es true, recurrir a la capacidad de nulos, de lo contrario el valor.
Momento en el que se produce el disparo. Sin razón aparente compilador de VB decide que el tipo base común para Nothing y Integer es Integer, en cuyo punto se traduce en silencio a la declaración:

i = If(condition(), 0, 42)

Ahora, si tuviera que hacer esto en C #:

i = (condition()) ? null : 42;

obtendría inmediatamente un error de compilación diciendo que <null> no se combina bien con int. Lo cual es genial, ya que mi pie habría sido más saludable tenían fui el C # forma en este momento. Y para que esto compilar, usted tiene que escribir explícitamente:

i = (condition()) ? null : (int?)42;

Ahora, puede hacer lo mismo en VB y obtener la correcta nula-dad que se puede esperar:

i = If(condition(), Nothing, CType(42, Integer?))

Pero eso requiere tener su toma pie en el primer lugar. No hay error de compilación y no hay ninguna advertencia. Que de con Explicit On y Strict On.


Así que mi pregunta es, ¿por qué?
¿Debo tomar esto como un error del compilador?
O puede alguien explicar por qué el compilador se comporta de esta manera?

¿Fue útil?

Solución

Esto se debe a Nothing de VB no es un equivalente directo a null C # 's.

Por ejemplo, en C # este código no se compilará:

int i = null;

Sin embargo, este código VB.Net funciona bien:

Dim i As Integer = Nothing

de VB.Net Nothing es en realidad una aproximación más exacta para la expresión default(T) C # 's.

Otros consejos

El operador ternario sólo puede devolver un tipo.

En C #, pero intenta elegir un tipo basado en null y 42. Bueno, null no tiene un tipo, por lo que decide que el tipo de retorno del operador ternario es el de 42; int un simple y llano. A continuación, se queja porque no se puede devolver null como un viejo int llanura. Al obligar a 42 como int?, el operador ternario va a devolver un int?, por lo que de null válida.

Ahora, no sé sobre VB, pero citando el MSDN, España Assigning Nothing to a variable sets it to the default value for its declared type.

que, desde VB determina que el operador ternario devolverá un int (utilizando el mismo proceso C # DID), Nothing es 0. Una vez más, coaccionando el 42 a ser un int? Nothing se convierte en el valor predeterminado de int?, que es null, como se esperaba.

Estoy pensando que esto tiene algo que ver con SI que con nada. Considere este código:

''#     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)

¿Por qué está haciendo esto todavía no sé, probablemente, una pregunta para el equipo de VB. No creo que esto tiene que ver con la palabra clave Nada o anulable.

Nothing y null no son la misma cosa ... desde el MSDN:

  

Nada Asignación a una variable lo establece en el valor predeterminado para su tipo declarado.

también

  

Si proporciona un tipo de valor en la expresión, IsNothing siempre devuelve Falso.

Tenga en cuenta que int? es un tipo anulable, pero aún así es un tipo de valor, no un tipo de referencia.

Inténtelo de DbNull.Value al lugar de Nothing ...

En una serie de casos Nothing conseguirá convertido en el valor predeterminado. Para uso Nothing la misma manera que utilizaría null lo que necesita para su emisión al tipo anulable correcta.

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))

Esto sucede porque Entero no es un tipo de referencia. 'Nada' se supone que sólo el trabajo de los tipos de referencia. Para los tipos de valor asignación Nada se convierte automáticamente en el valor predeterminado, que es en el caso de un número entero 0.

Esto es realmente posible ahora en VS2015 (por lo menos) mediante el uso de Nueva entero?

Ej .:

  

Si (testInt> 0, testInt, Nueva entero?), Donde testInt es de tipo entero?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top