0

If I declare a string but do not assign a value, the Equals function throws an exception but it doesn't throw an exception if it is compared to a value.

The error list warns about the problem:

Warning BC42104 Variable a is used before it has been assigned a value. A null reference exception could result at runtime.

Dim a As String
Dim b as string = "bar"

a.Equals("foo") 'causes System.NullReferenceException

a = "foo" 'No exception although a is nothing

a = b 'No exception although a is nothing

I know the warning says it COULD cause an exception, but does anyone know why this is the happening?

Milo
  • 3,365
  • 9
  • 30
  • 44
Uggy
  • 3
  • 2
  • 1
    [Nothing and Strings in Visual Basic](https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/strings/nothing-and-strings) – TnTinMn Mar 27 '19 at 19:09
  • The warning is pretty much unrelated. It can always be `Nothing`, even if initialized; for example, the warning will go away if you write `Dim a As String = Nothing`. Is your real question about the difference between the `=` operator and the `.Equals` method? – Ry- Mar 27 '19 at 19:15
  • 1
    `a.Equals` is calling a *member function* on `a`. Obviously you cannot call a member function on an object that is "null"/Nothing. However, the equality operator is special-cased to handle null objects. – Cody Gray - on strike Mar 27 '19 at 19:16
  • 1
    (Also, please confirm that you’re using `a = "foo"` and `a = b` in an expression and not as a statement – preferably with real code – because it’s also a valid assignment statement. Since you already got an answer that was confused about that.) – Ry- Mar 27 '19 at 19:16
  • 1
    To elaborate on what @CodyGray is saying, also note that [`string.operator==(string, string)`](https://referencesource.microsoft.com/#mscorlib/system/string.cs,705), like all overloaded operators, is `static` (`Shared`), at no point does the .NET framework try to do `a.Equals` when it handles the `=` operator; [`string.Equals(string)`](https://referencesource.microsoft.com/#mscorlib/system/string.cs,570), on the other hand is an instance method of `String` and will cause a `NullReferenceException`. – jrh Mar 27 '19 at 19:20
  • Yes, these were in If statements – Uggy Mar 28 '19 at 08:46
  • @TnTinMn: This behaviour has nothing to do with the “Nothing and Strings in Visual Basic” article, since VB compatibility functions aren’t involved. – Ry- Mar 28 '19 at 22:59
  • @Ry, the question is slightly ambiguous in that the OP is performing string comparison operations. Comparison is confirmed by the OP in a comment to the accepted answer. VB string comparisons can be a mine-field for those that do not know the language. The Nothing(null) equal String.Empty ("") is one, Another is the `Option Compare Text` directive that causes `"a" = "A"` to equate to True. What does have absolutely nothing to do with this question is the duplicate hammer placed by Cody Gray. Maybe [Nothing = String.Empty (Why are these equal?)](https://stackoverflow.com/questions/2633166) – TnTinMn Mar 29 '19 at 01:15
  • @TnTinMn: But the question was why the comparison didn’t throw an exception. I don’t see the OP mentioning its value. – Ry- Mar 29 '19 at 01:33
  • @Ry, From the VB language specification, Section 11.14: _When doing a string comparison, a null value is equivalent to the string literal ""_. So `a = "foo"` (a is Nothing) is evaluated as `"" = "foo"`. That is not the actual implementation as there is no substitution of "" for a null string; it is implemented by calling the `Microsoft.VisualBasic.CompilerServices.CompareString(String, String, Boolean) Method`. As passing `Nothing` to that method is valid, there will be no exception thrown. – TnTinMn Mar 29 '19 at 02:08
  • @TnTinMn: Yeah, but it’s not an exception in C# either. It’s just `false`. The reason it’s *able* to not be an exception is because the operator isn’t an instance method. – Ry- Mar 29 '19 at 02:15
  • @ry, No, its an implementation detail in which the implementation does not throw an exception with a null argument. But I doubt you will be convinced by that argument. – TnTinMn Mar 29 '19 at 02:50
  • @TnTinMn: Sure, it’s part of the implementation, but `"".Equals(Nothing)` doesn’t throw an exception either, because it’s part of *that* implementation. `Nothing.Equals("")` doesn’t even have to involve implementation; it can’t possibly work, because it’s not an extension method. I think that’s the most accurate answer to the question as posed. – Ry- Mar 29 '19 at 02:52

1 Answers1

1

This is because Dim a As String declares the type of variable a but doesn't assign anything to it. This is basically saying : "This variable was made to hold a String object, but it doesn't hold any right now". On the other hand, Dim b As String = "bar" declares the variable and its type, but also assigns a String object to it ("bar"). The reason a.Equals("foo") returns an exception is because you only declared it without assigning anything to it (so you are trying to access an object that isn't there). a = "foo" works because you are assigning a String object of value "foo" to the variable a. It's like saying : "This variable now holds a String object with value 'foo'".

Edit :

While your code points to the assignment of the variable a, I was made aware that you wanted to know why the = operator, as a comparison operator, works. This is because what I said earlier isn't entirely true when I said it didn't hold an object. It actually is of Nothing value (which sets it as a null reference) if no String object was assigned to it (String is a nullable object).

See : https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/nothing

Hope this helps.

Olivier Samson
  • 609
  • 4
  • 13
  • The question is about string comparison -- "it doesn't throw an exception if it is compared to a value". The code presented leads one to assume it is about assignment. – TnTinMn Mar 27 '19 at 19:13
  • @TnTinMn this is true. I was looking at the code given. If the `a = "foo"` expression is used in an If statement, I assume it works because a is treated as a Nothing object, which works with the = operator. – Olivier Samson Mar 27 '19 at 19:25
  • You might as well cover both contingencies in your answer before someone else does. Also look at the link I posted as comment. – TnTinMn Mar 27 '19 at 19:30
  • Yes this was in an If statement. Hence I was expecting an exception (like in C#) but reading TnTinMn link I see now that the VB runtime treats a string of nothing as an empty string, which now makes sense of this. – Uggy Mar 28 '19 at 08:42
  • @Uggy: ”Like in C#” – ? `null == "foo"` works fine in C# too with no exception. – Ry- Mar 28 '19 at 20:35