2010-06-25 13 views
9

W VB.NET, jaka jest różnica międzyJaka jest różnica między "foo = Nothing" i "foo is Nothing" w VB.NET?

if foo is Nothing Then 
     doStuff() 
End If 

i

if foo=Nothing Then 
    doStuff() 
End If 

aktualizacji Otrzymałem następującą odpowiedź:

foo is Nothing po prostu sprawdza czy foo nie jest przypisane do żadnego odniesienia. foo = Nothing sprawdza, czy referencja posiadana przez foo jest równa nothing.

Po uruchomieniu trzy oświadczenia,

Dim foo as Object 
Dim bar as Integer 
foo = bar 

foo is Nothing wartość false i foo = Nothing wartość true.

Jednak jeśli bar jest zadeklarowana jako Object i nie zainicjowany, następnie foo is Nothing i foo = Nothing zarówno oceny true! Myślę, że to dlatego, że Integer jest typem wartości, a Object jest typem odniesienia.

Odpowiedz

10

To zależy od typu.

  • Na typów wartości, Isnie działa, tylko = i Nothing odnosi się do standardowego przykład tego typu (tznwystąpienie, które można uzyskać, dzwoniąc pod numer New T() dla danego typu: T).

  • Na typów odniesienia, Is wykonuje porównawczy (identyczną object.ReferenceEquals(a, Nothing)). a = Nothing zwykle nie działa, chyba żeOperator = zostało jawnie zdefiniowane dla tej klasy.

    Jeśli ponadto Operator = została zrealizowana prawidłowo, a następnie foo = Nothing i foo Is Nothing powinno dawać ten sam wynik (ale to samo nie jest prawdą dla każdej innej wartości zamiast Nothing) ale foo Is Nothing będzie bardziej skuteczny, ponieważ jest to kompilator nieodłączną podczas gdy Operator = wywoła metodę.

  • Dla typy wartości pustych (czyli instancje Nullable(Of T)) obowiązują specjalne zasady: jak wszystkie inne podmioty, = jest lifted (zauważysz błąd w tym blogu ...) przez kompilator do typu bazowego. Wynik porównania dwóch Nullable s nie jest zatem Boolean, ale (uwaga: ?). Jednak ze względu na tak zwaną "propagację zerową" dla operatorów zniesionych, będzie to zawsze zawsze zwracać Nothing, bez względu na wartość foo. Cytowanie Visual Basic 10 language specification (§1.86.3): (sic!)

    Jeśli argument jest Nothing eteru, wynikiem wyrażenia jest wartość Nothing wpisane jako wartości pustych wersji typu wynikowego.

    Więc jeśli użytkownik chce porównać zmienną Nullable do Nothing, muszą stosować składnię foo Is Nothing dla których, po raz kolejny, kompilator generuje specjalny kod, aby to działało (§1.79.3 Visual Basic 10 specyfikacja językowa). Czapka z kapeluszem dla Jonathana Allena za (poprawne) upieranie się, że się myliłem; czubek kapelusza do Jareda Parsonsa za przekazanie mi linku do specyfikacji Visual Basic 10.

(Powyższe zakłada, że ​​Option Strict On służy, jak zawsze powinna. W przypadku, gdy nie jest to przypadek, wyniki będą różnić się nieznacznie od nazywając foo = Nothing może wykonywać późny związana połączenia).

+0

W przypadku ciągów = i daje różne wyniki, daresay = realizuje się z zasadą najmniejszego zaskoczenia dla ciągów, więc uważam, że jest to poprawne. –

+0

@Lasse: Tak, łańcuchy znaków są szczególnym przypadkiem w VB, ponieważ '=' wywoła specjalną metodę zamiast 'Equals', która potraktuje" Nic "jako równy pustemu łańcuchowi znaków. –

+1

Zapomniałeś Nullable (Of T). Dla tego 'foo = Nothing' skompiluje się, ale daje złą odpowiedź. –

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` 

W VB, oba twierdzenia oceni tę samą wartość, jeśli foo nie został zainicjowany

+0

Co jeśli foo nie jest typem referencyjnym? A co jeśli foo jest ciągiem? Jesteś pewien, że oceni on tę samą wartość? –

+0

Typy wartości wchodzą w grę, gdy metoda jest ogólna, ale w przypadku pustego łańcucha (np. ""), A następnie Is i = spowoduje inne wyniki. –

+0

@Lasse, Zobacz moją odpowiedź na kiedy foo jest Nullable (Of T). –

2

Oto niektóre IL, aby potwierdzić różnice:

.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 
} 

kod 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 
+0

Spróbuj także z ciągiem zawierającym Nic, ciągiem zawierającym "" i typem wartości, powiedzmy liczbą całkowitą, i użyj zarówno wartości domyślnej dla typu wartości, jak i czegoś innego, tj. zostaw to na 0, a następnie sprawdź także na 1. –

+0

@Lasse - Nie mam czasu, aby dodać więcej przykładów, których się boję. Może ktoś inny może to zrobić dla odniesienia? –

1

foo jest wskaźnikiem do miejsca w pamięci i nic nie znaczy "nie wskazuje na mnie ponieważ pamięć nie została jeszcze przydzielona ". Oznacza to, że porównując 2 typy wartości, mają tę samą wartość. Ale zakładasz, że foo reprezentuje obiekt, który jest zawsze typem odniesienia, który ma wskazywać na obiekt w pamięci. "jest" służy do porównywania typów obiektów i zwraca wartość "prawda" tylko wtedy, gdy dwa obiekty wskazują tę samą wartość.

Say masz clsFoo z jednej liczby całkowitej publicznych państw zmiennej „x” i foo1 i foo2 są zarówno clsFoo, a y i z są liczbami całkowitymi

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. 

NIGDY zapomnij włączyć opcji ścisłego dalej. Aby tego uniknąć, należy krzyczeć: "PROSZĘ, aby mój program SUKCIE".

+0

Wygląda na to, że zapomniałeś o strukturach zerowalnych, które powinny używać 'Is Nothing' zamiast' = Nothing'. –

+0

Pytanie o op nie wymagało dokładnie takich szczegółów, chyba że przedstawiał je jako konkurs ;-) – FastAl

1

asume:

MojaFunkcja (foo jako obiekt)

Foo - Boxed jeśli ValueType

jeśli foo is Nothing Następnie

przedmiot.ReferenceEquals (Kod inlined - Najszybsza metoda)

jeśli foo = Nothing Następnie

Operators.ConditionalCompareObjectEqual (foo, Nic, False)

Vb.Net nieść tę sprawę jak obj1 = Obj2. To nie używa Obj.equals (obj2)! Wyjątek, jeśli Obj1 jest niczym.

Ta opcja używa bardzo złożonego kodu, ponieważ istnieje wiele opcji w zależności od wszystkich możliwych definicji foo.

spróbuj tego:

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

To zależy od typu Foo.

typy odwołań

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 

typów wartości

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 

Typy dopuszczające wartość null Wartość

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 

Wielu ludzi nie rozumie Null Propogation w VB. Podobnie jak SQL, używa logiki trójwartościowej, więc odpowiedź dla "a = b" może być True, False lub Null. W instrukcji If wartość Null jest traktowana jako Fałsz.

Ostrzeżenie Nie można po prostu napisać If Not(Foo = Nothing) Then bo „nie (Nic)” jest nadal „nic”.

Powiązane problemy