Каково различие между 'нечто =, Ничто' и 'нечто - Ничто' в 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 оценивает ко лжи и foo = Nothing оценивает к истинному.

Однако, если bar объявляется как Object и не инициализированный, затем foo is Nothing и foo = Nothing оба оценивают к истинному! Я думаю, что это вызвано тем, что Integer тип значения и Object ссылочный тип.

10
задан Peter Mortensen 20 April 2012 в 09:06
поделиться

6 ответов

Зависит от типа.

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

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

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

  • Для типов значений, допускающих значение NULL (т. Е. Экземпляров Nullable (Of T) ), применяются особые правила: как и все другие операторы, = равно поднял (обратите внимание на ошибку в этом сообщении в блоге ...) компилятором к базовому типу. Таким образом, результат сравнения двух Nullable s не Boolean , а Boolean? (обратите внимание на ? ). Однако из-за так называемого «нулевого распространения» для поднятых операторов это всегда возвращает Nothing , независимо от значения foo . Цитата из спецификации языка Visual Basic 10 (§1.86.3):

    Если эфирный (sic!) Операнд равен Ничего , результатом выражения будет значение ] Ничего не введено в качестве версии типа результата, допускающей значение NULL.

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

(Выше предполагается, что используется Option Strict On , так как вы всегда должны . Если это не так, результаты будут немного отличаться после вызова foo = Ничто не может выполнять вызов с поздним связыванием.)

11
ответ дан 3 December 2019 в 20:02
поделиться

Вот некоторые 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
2
ответ дан 3 December 2019 в 20:02
поделиться
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 не был инициализирован

3
ответ дан 3 December 2019 в 20:02
поделиться

Это зависит от типа 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

Многие люди не понимают, что такое Null Propogation в VB. Как и SQL, она использует логику трех значений, поэтому ответ на вопрос "a=b" может быть True, False или Null. В операторе If Null рассматривается как False.

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

1
ответ дан 3 December 2019 в 20:02
поделиться

Asume:

MyFunc(Foo as object)

Foo - Boxed if ValueType

if foo is Nothing Then

object.ReferenceEquals (Code Inlined - самый быстрый метод)

if foo=Nothing Then

Operators.ConditionalCompareObjectEqual(foo, Nothing, False)

Vb.Net выполняет этот случай как Obj1 = Obj2. Он не использует Obj.equals(obj2)! Exception if Obj1 is nothing

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

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

Sub Main()
 Dim o As Object = 0
 Debug.Print(o Is Nothing) 'False
 Debug.Print(o = Nothing) 'True 
End Sub
1
ответ дан 3 December 2019 в 20:02
поделиться

foo - это указатель на ячейку памяти, а Nothing означает «не указывает ни на какую память, потому что память еще не была выделена». Равно означает, что при сравнении двух типов значений они имеют одинаковое значение. Но вы предполагаете, что foo представляет объект, который всегда является ссылочным типом, который должен указывать на объект в памяти. «is» используется для сравнения типов объектов и возвращает «истину» только в том случае, если у вас есть два объекта, указывающих на одно и то же значение.

Скажем, у вас есть 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.

НИКОГДА не забудьте включить option strict. Если это не удастся, значит крикнуть: «ПОЖАЛУЙСТА, ПОЖАЛУЙСТА, ОТСИЛИ мою программу».

1
ответ дан 3 December 2019 в 20:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: