In VB.NET, what is the difference between
if foo is Nothing Then
doStuff()
End If
and
if foo=Nothing Then
doStuff
Asume:
MyFunc(Foo as object)
Foo - Boxed if ValueType
if foo is Nothing Then
object.ReferenceEquals (Code Inlined - Fastest method)
if foo=Nothing Then
Operators.ConditionalCompareObjectEqual(foo, Nothing, False)
Vb.Net carry this case like Obj1 = Obj2. It do´nt uses Obj.equals(obj2) ! Exception if Obj1 is nothing
This option uses a very complex code as there are a lot options depending all posible foo definitions.
try this:
Sub Main() Dim o As Object = 0 Debug.Print(o Is Nothing) 'False Debug.Print(o = Nothing) 'True End Sub
foo is a pointer to a memory location and Nothing means 'not pointing to any memory because no memory has been allocated yet'. Equals means that when you are comparing 2 value types they have the same value. But you're assuming foo represents an object, which is always a reference type that is meant to point to an object in memory. 'is' is for comparing object types and will only return 'true' if you have two objects pointing to the same value.
Say you have clsFoo with one public integer member variable 'x' and foo1 and foo2 are both clsFoo, and y and z are integers
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.
NEVER forget to turn option strict on. To fail this is to scream 'PLEASE make my program SUCK.'
It depends on Foo's type.
Reference Types
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
Value Types
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
Nullable Value Types
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
A lot of people don't understand Null Propogation in VB. Like SQL, it uses three-value logic so the answer for "a=b" could be True, False, or Null. In an If
statement a Null is treated as a False.
Warning You can't just write If Not(Foo = Nothing) Then
because 'Not (Nothing)' is still 'Nothing'.
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`
In VB, both statements will evaluate to the same value if foo
has not been initialised
Here's some IL to validate the differences:
.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
}
VB Code:
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
It depends on the type.
For value types, Is
doesn’t work, only =
, and Nothing
refers to the default instance of that type (i.e. the instance that you get by calling New T()
for a given type T
).
For reference types, Is
performs a reference comparison (identical to object.ReferenceEquals(a, Nothing)
). a = Nothing
usually does not work, unless Operator =
has explicitly been defined for that class.
If, furthermore, Operator =
has been implemented correctly, then foo = Nothing
and foo Is Nothing
should yield the same result (but the same isn’t true for any other value instead of Nothing
) but foo Is Nothing
will be more efficient since it’s a compiler intrinsic while Operator =
will call a method.
For nullable value types (i.e. instances of Nullable(Of T)
), special rules apply: like all other operators, =
is lifted (notice the error in that blog post …) by the compiler to the underlying type. The result of comparing two Nullable
s is thus not Boolean
but Boolean?
(note the ?
). However, because of so-called “null propagation” for lifted operators, this will always return Nothing
, no matter the value of foo
. Quoting the Visual Basic 10 language specification (§1.86.3):
If ether (sic!) operand is
Nothing
, the result of the expression is a value ofNothing
typed as the nullable version of the result type.
So if the users want to compare a Nullable
variable to Nothing
, they must use the foo Is Nothing
syntax for which, once again, the compiler generates special code to make it work (§1.79.3 of the Visual Basic 10 language specification).
Hat tip to Jonathan Allen for (correctly) persisting that I was wrong; hat tip to Jared Parsons for passing me a link to the Visual Basic 10 specification.
(The above assumes that Option Strict On
is used, as you always should. In case that isn’t the case, the results will differ slightly since calling foo = Nothing
may perform a late-bound call.)