В чем разница между "foo = Nothing" и "foo is Nothing" в VB.NET?

в 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 Nothing и foo = Nothing оба оценивают на true! Я думаю, это потому, что Integer является типом значения и Object является ссылочным типом.

6 ответов


это зависит от типа.

  • на типы значений, Is не работает, только = и Nothing ссылается на экземпляр по умолчанию этого типа (т. е. экземпляр, который вы получаете, вызывая New T() для данного типа T).

  • на ссылка типа, Is выполняет сравнение ссылок (идентично object.ReferenceEquals(a, Nothing)). a = Nothing обычно не работает, если Operator = было явно определено для этого класса.

    если, кроме того, Operator = было реализовано правильно, тогда foo = Nothing и foo Is Nothing должен дать тот же результат (но то же самое не верно для любого другого значения вместо Nothing), но foo Is Nothing будет более эффективным, так как это встроенный компилятор while Operator = вызывает метод.

  • на типы значений nullable (т. е. экземпляра Nullable(Of T)), специальные правила: как и все другие операторы, = is поднял (обратите внимание на ошибку в этом сообщении в блоге ...) компилятором для базового типа. Результат сравнения двух Nullables, таким образом, не Boolean но Boolean? (обратите внимание на ?). Однако из-за так называемого "нулевого распространения" для поднятых операторов это будет всегда возвращение Nothing, независимо от значения foo. Цитируя язык Visual Basic 10 спецификация (§1.86.3):

    если эфир (sic!) операнд Nothing, результатом выражения является значение Nothing типизировано как nullable версия типа результата.

    поэтому, если пользователи хотят сравнить Nullable переменная Nothing, они должны использовать foo Is Nothing синтаксис, для которого компилятор снова генерирует специальный код, чтобы заставить его работать (§1.79.3 спецификации языка Visual Basic 10). наконечник шляпы Джонатану Аллен (правильно) настаивает, что я был неправ; совет шляпы Джареду Парсонсу за передачу мне ссылки на спецификацию Visual Basic 10.

(выше предполагает, что Option Strict On используется, как вы всегда должны. В случае, если это не так, результаты будут немного отличаться с момента вызова foo = 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`

в VB оба оператора будут оценивать одно и то же значение, если foo не было инициализировано


вот некоторые 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

foo-это указатель на местоположение памяти, и ничто не означает "не указывать на память, потому что память еще не выделена". Equals означает, что при сравнении 2 типов значений они имеют одинаковое значение. Но вы предполагаете, что foo представляет объект, который всегда является ссылочным типом, который предназначен для указания на объект в памяти. "is" предназначен для сравнения типов объектов и возвращает "true", только если у вас есть два объекта, указывающие на одно и то же значение.

скажем, у вас есть clsFoo с одной открытой целочисленной переменной-членом " x " и 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.

никогда забудьте включить опцию strict on. Потерпеть неудачу - это кричать: "пожалуйста, сделайте мою программу сосать.'


Asume:

MyFunc (Foo как объект)

Foo-Boxed если ValueType

если foo-ничто, то

этот параметр использует очень сложный код, так как есть много вариантов, зависящих от всех возможных определений foo.

попробуйте это:

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

Это зависит от типа Фу.

Ссылка Типа

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

Типы Значений Nullable

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. Как и SQL, он использует трехзначную логику, поэтому ответ для "a=b" может быть True, False или Null. В If оператор a Null рассматривается как False.

предупреждение вы не можете просто написать If Not(Foo = Nothing) Then потому что "не (ничего)" по-прежнему "ничего".