В чем разница между "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
будет более эффективным, так как это встроенный компилятор whileOperator =
вызывает метод. -
на типы значений nullable (т. е. экземпляра
Nullable(Of T)
), специальные правила: как и все другие операторы,=
is поднял (обратите внимание на ошибку в этом сообщении в блоге ...) компилятором для базового типа. Результат сравнения двухNullable
s, таким образом, не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
потому что "не (ничего)" по-прежнему "ничего".