VB.NET中'foo = Nothing'和'foo is Nothing'有什么区别?

时间:2010-06-25 13:18:25

标签: vb.net syntax null

VB.NET中,

之间有什么区别
if foo is Nothing Then
      doStuff()
End If

if foo=Nothing Then
    doStuff()
End If

更新我收到了以下答案:

  

foo is Nothing只检查foo是否未分配给任何参考。   foo = Nothing会检查foo所持有的引用是否等于nothing

运行三个语句后,

Dim foo as Object
Dim bar as Integer
foo = bar

foo is Nothing评估为false,foo = Nothing评估为true。

但是,如果bar被声明为Object而未初始化,那么foo is Nothingfoo = Nothing都会评估为真!我认为这是因为Integer是值类型而Object是引用类型。

6 个答案:

答案 0 :(得分:11)

取决于类型。

  • 对于值类型Is 不起作用,只有=,而Nothing指的是该类型的默认实例(即通过为给定类型New T()调用T获得的实例)。

  • 对于参考类型Is执行参考比较(与object.ReferenceEquals(a, Nothing)相同)。 a = Nothing通常不起作用除非为该类明确定义 Operator =

    此外,如果Operator =已正确实施,那么foo = Nothingfoo Is Nothing应该会产生相同的结果(但对于任何其他值而不是{{ 1}})但是Nothing会更高效,因为它是编译器内在的,而foo Is Nothing会调用方法。

  • 对于可空值类型(即Operator =的实例),适用特殊规则:与所有其他运算符一样,Nullable(Of T)lifted(通知该博客文章中的错误...)由编译器到底层类型。因此,比较两个= s的结果不是Nullable而是Boolean(请注意Boolean?)。但是,由于提升运算符的所谓“空传播”,无论?的值如何,总是返回Nothing。引用Visual Basic 10 language specification(§1.86.3):

      

    如果ether(sic!)操作数是foo,则表达式的结果是Nothing的值,作为结果类型的可空版本输入。

    因此,如果用户想要将Nothing变量与Nullable进行比较,则必须使用Nothing语法,编译器再次生成特殊代码以使其工作( Visual Basic 10语言规范的§1.79.3)。 向Jonathan Allen提示(正确)坚持说我错了;向Jared Parsons提示,向我传递了Visual Basic 10规范的链接。

(以上假设使用foo Is Nothing,因为总是应该。如果不是这种情况,结果会略有不同,因为调用Option Strict On可能会执行后期约会。)

答案 1 :(得分: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`

在VB中,如果foo尚未初始化

,则两个语句将评估为相同的值

答案 2 :(得分:2)

以下是一些用于验证差异的IL:

.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代码:

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

答案 3 :(得分:1)

foo是指向内存位置的指针,Nothing意味着“没有指向任何内存,因为还没有分配内存”。等于意味着当您比较2个值类型时,它们具有相同的值。但是你假设foo代表一个对象,它总是一个指向内存中对象的引用类型。 'is'用于比较对象类型,如果有两个对象指向相同的值,则只返回'true'。

假设您有一个公共整数成员变量'x'的clsFoo,而foo1和foo2都是clsFoo,而y和z是整数

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.

从不忘记打开选项严格。为了失败,这就是尖叫'请让我的程序消失。'

答案 4 :(得分:1)

Asume:

  

MyFunc(Foo作为对象)

Foo - 如果ValueType

,则装箱

如果foo是Nothing那么

  

object.ReferenceEquals(代码内联 - 最快的方法)

如果foo = Nothing那么

  

Operators.ConditionalCompareObjectEqual(foo,Nothing,False)

Vb.Net就像Obj1 = Obj2一样携带这种情况。 它没有使用Obj.equals(obj2)!如果Obj1什么都不是

,则例外

此选项使用非常复杂的代码,因为根据所有可能的foo定义,有很多选项。

试试这个:

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

答案 5 :(得分:1)

这取决于Foo的类型。

参考类型

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

价值类型

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

可空值类型

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

很多人不了解VB中的Null Propogation。与SQL一样,它使用三值逻辑,因此“a = b”的答案可能是True,False或Null。在If语句中,Null被视为False。

警告您不能只写If Not(Foo = Nothing) Then,因为'Not(Nothing)'仍然是'Nothing'。

相关问题