В 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
ссылочный тип.
Зависит от типа.
Для типов значений , 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 = Ничто
не может выполнять вызов с поздним связыванием.)
Вот некоторые 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 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
не был инициализирован
Это зависит от типа 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".
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
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. Если это не удастся, значит крикнуть: «ПОЖАЛУЙСТА, ПОЖАЛУЙСТА, ОТСИЛИ мою программу».