2010-06-25 21 views
9

En VB.NET, ¿cuál es la diferencia entre¿Cuál es la diferencia entre 'foo = Nothing' y 'foo is Nothing' en VB.NET?

if foo is Nothing Then 
     doStuff() 
End If 

y

if foo=Nothing Then 
    doStuff() 
End If 

actualización recibí la siguiente respuesta:

foo is Nothing simplemente comprueba si foo no está asignado a ninguna referencia. foo = Nothing comprueba si la referencia mantenida por foo es igual a nothing.

Después de ejecutar los tres estados,

Dim foo as Object 
Dim bar as Integer 
foo = bar 

foo is Nothing evalúa como falsa y foo = Nothing un resultado verdadero.

Sin embargo, si bar se declara como Object y no se inicializa, entonces foo is Nothing y foo = Nothing ambos se evalúan como verdaderos. Creo que esto se debe a que Integer es un tipo de valor y Object es un tipo de referencia.

Respuesta

10

Depende del tipo.

  • Para tipos de valor, Isno funciona, solamente =, y Nothing se refiere a la instancia predeterminada de ese tipo (es decir,la instancia que obtiene llamando al New T() para un tipo dado T).

  • Para tipos de referencia, Is realiza una comparación de referencia (idéntico a object.ReferenceEquals(a, Nothing)). a = Nothing normalmente no funciona, a menos queOperator = se haya definido explícitamente para esa clase.

    Si, por otra parte, Operator = se ha implementado correctamente, entonces foo = Nothing y foo Is Nothing debe producir el mismo resultado (pero lo mismo no es cierto para cualquier otro valor en lugar de Nothing) pero foo Is Nothing será más eficiente, ya que es un compilador intrínseca mientras que Operator = llamará a un método.

  • Para tipos de valor anulable (es decir, las instancias de Nullable(Of T)), se aplican reglas especiales: al igual que todos los demás operadores, = es lifted (notar el error en ese blog ...) por el compilador para el tipo subyacente. El resultado de comparar dos Nullable s no es Boolean, sino Boolean? (tenga en cuenta ?). Sin embargo, debido a la llamada "propagación nula" para operadores levantados, esto siempre devuelve Nothing, sin importar el valor de foo. Citando al Visual Basic 10 language specification (§1.86.3): (sic)

    Si éter operando es Nothing, el resultado de la expresión es un valor de Nothing escrito como la versión anulable del tipo de resultado.

    Así que si los usuarios desean comparar una variable Nullable a Nothing, se debe utilizar la sintaxis foo Is Nothing para lo cual, una vez más, el compilador genera código especial para que funcione (§1.79.3 del Visual Basic 10 especificación del lenguaje). Sombrero de punta a Jonathan Allen para persistir (correctamente) que estaba equivocado; Un consejo para Jared Parsons por pasarme un enlace a la especificación de Visual Basic 10.

(Lo anterior supone que se utiliza Option Strict On, a medida que siempre debe. En caso de que no es el caso, los resultados difieren ligeramente desde llamando foo = Nothing puede realizar una llamada de enlace en tiempo.)

+0

Para cadenas = y produce resultados diferentes, me atrevo a decir = se implementa con el principio de menor sorpresa para las cadenas así que lo considero correcto. –

+0

@Lasse: Sí, las cadenas son un caso especial en VB, ya que '=' llamará a un método especial en lugar de 'Equals', que tratará' Nothing' igual a la cadena vacía. –

+1

Olvidó Nullable (Of T). Para eso 'foo = Nothing' compilará, pero da la respuesta incorrecta. –

3
foo is Nothing simply checks if `foo` is not assigned to any reference. 

foo=Nothing checks if the reference held by `foo` is equal to `nothing` 

En VB, ambos estados evaluarán en el mismo valor si foo no se ha inicializado

+0

¿Qué pasa si foo no es un tipo de referencia? ¿O qué pasa si foo es una cadena? ¿Estás seguro de que evaluará el mismo valor? –

+0

Los tipos de valor entran en juego cuando el método es genérico, pero para una cadena en blanco (es decir, ""), entonces Is y = producirán resultados diferentes. –

+0

@Lasse, ver mi respuesta para cuando foo es un Nullable (De T). –

2

aquí hay algo de IL para validar las diferencias:

.method public static void Main() cil managed 
{ 
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() 
    .entrypoint 
    .maxstack 3 
    .locals init (
     [0] object o, 
     [1] bool VB$CG$t_bool$S0) 
    L_0000: nop 
    L_0001: newobj instance void [mscorlib]System.Object::.ctor() 
    L_0006: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object) 
    L_000b: stloc.0 
    L_000c: ldloc.0 
    L_000d: ldnull 
    L_000e: ceq 
    L_0010: stloc.1 
    L_0011: ldloc.1 
    L_0012: brfalse.s L_001f 
    L_0014: ldstr "Is Nothing" 
    L_0019: call void [mscorlib]System.Console::WriteLine(string) 
    L_001e: nop 
    L_001f: nop 
    L_0020: ldloc.0 
    L_0021: ldnull 
    L_0022: ldc.i4.0 
    L_0023: call bool [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Operators::ConditionalCompareObjectEqual(object, object, bool) 
    L_0028: stloc.1 
    L_0029: ldloc.1 
    L_002a: brfalse.s L_0037 
    L_002c: ldstr "Is nothing" 
    L_0031: call void [mscorlib]System.Console::WriteLine(string) 
    L_0036: nop 
    L_0037: nop 
    L_0038: nop 
    L_0039: ret 
} 

Código VB:

Sub Main() 
     Dim o As New Object 

     If o Is Nothing Then 
      Console.WriteLine("Is Nothing") 
     End If 

     If o = Nothing Then 
      Console.WriteLine("Is nothing") 
     End If 
    End Sub 
+0

También intente esto con una cadena que contenga Nothing, una cadena que contenga "", y un tipo de valor, digamos un entero, y use tanto el valor predeterminado para el tipo de valor como otra cosa, es decir. déjalo en 0, y luego busca 1 también. –

+0

@Lasse - No tengo tiempo para agregar más ejemplos, me temo. ¿Tal vez alguien más puede hacer esto como referencia? –

1

foo es un puntero a una ubicación de memoria y Nothing significa 'no apuntando a mí' mory porque aún no se ha asignado memoria '. Igual significa que cuando comparas 2 tipos de valores tienen el mismo valor. Pero supone que foo representa un objeto, que siempre es un tipo de referencia que apunta a un objeto en la memoria. 'es' es para comparar tipos de objetos y solo devolverá 'verdadero' si tiene dos objetos apuntando al mismo valor.

Digamos que tiene clsFoo con un miembro variable entera pública 'x' y foo1 y foo2 son tanto clsFoo, e Y y Z son enteros

foo1=new clsFoo 
foo2=new clsFoo 
foo1.x=1 
foo2.x=1 
y=2 
z=1 
dim b as boolean 

b= foo1 is not foo2 ' b is true 
b= foo1.x=foo2.x ' b is tree 
b= foo1 is foo2 'b is false 
b= foo1.x=z ' true of course 
foo2.x=3 
b= foo1.x=foo2.x ' false of course 
foo1=foo2 
b=foo1 is foo2 ' now it's true 
b= foo1.x=foo2.x ' true again 
b= 3=3 ' just as this would be 
b= foo1=foo2 ' ERROR: Option Strict On disallows operands of type Object for operator '='. Use the 'Is' operator to test for object identity. 

NUNCA olvidan opción estricta a girar. Fracasar es gritar "POR FAVOR, haga que mi programa CHUPE".

+0

Parece que has olvidado Nullable Structures, que debería usar 'Is Nothing' en lugar de' = Nothing'. –

+0

La pregunta de la operación no pedía exactamente tales detalles, a menos que lo planteara como un concurso ;-) – FastAl

1

Asume:

MyFunc (Foo como objeto)

Foo - en caja si ValueType

si foo es nada entonces

objeto.ReferenceEquals (Código inline - El método más rápido)

si foo = nada entonces

Operators.ConditionalCompareObjectEqual (foo, Nada, False)

Vb.Net llevar este caso como Obj1 = Obj2. ¡No usa Obj.equals (obj2)! Excepción si Obj1 no es nada

Esta opción usa un código muy complejo ya que hay muchas opciones que dependen de todas las posibles definiciones de foo.

probar esto:

Sub Main() 
    Dim o As Object = 0 
    Debug.Print(o Is Nothing) 'False 
    Debug.Print(o = Nothing) 'True 
End Sub 
1

Depende del tipo de Foo.

tipos de referencia

if foo = Nothing then 'This depends on how the op_Equals operator is defined for Foo. If not defined, then this is a compiler error. 
if foo Is Nothing then 'Evaluates to True is foo is NULL 

Tipos de valor

if foo = Nothing then 'Evaluates to True is foo has the default value in every field. For most types the default is 0. 
if foo Is Nothing then 'Compiler Error 

Tipos de Valores anulables

if foo = Nothing then 'This always evaluates to false. In VB 10, this is a compiler warning 
if foo Is Nothing then 'Evaluates to True is foo.HasValue = False 

Mucha gente no entiende Null Propogation en VB. Al igual que SQL, utiliza lógica de tres valores, por lo que la respuesta para "a = b" podría ser True, False o Null. En una declaración If, un nulo se trata como falso.

Advertencia No puede simplemente escribir If Not(Foo = Nothing) Then porque 'Not (Nothing)' sigue siendo 'Nothing'.

Cuestiones relacionadas