Nothing equals String.Empty, null does not equal String.Empty, what am I missing here?

15,830

Solution 1

Nothing has a special meaning in VB for strings. To test whether a string reference is null, you need:

If value Is Nothing

From the VB comparison operators documentation:

Numeric comparisons treat Nothing as 0. String comparisons treat Nothing as "" (an empty string).

I suspect this is just for backward compatibility with VB6 - it's not something I'd be happy with, if I were a VB developer.

A comparison of the form

If value = Nothing

is compiled to a call to Microsoft.VisualBasic.CompilerServices.Operators.CompareString which returns 0 (i.e. equal) if one operand is null and the other is empty.

Solution 2

In vb6, the default value for a string variable was an empty string. A vb6 programmer relying upon such behavior would be no "worse" than a C programmer relying upon default-zero initialization of int variables; both behaviors were specified as part of the language.

Further, in COM (the framework upon which previous versions of VB6 were based), any time a reference to string was created, someone would have to manually dispose of it. Since the most commonly used string was the empty string, many COM methods are explicitly documented as regarding a null pointer as equivalent to an empty string. This means that a function returning an empty string or passing one as a value parameter or returning one may simply pass a null pointer without having to allocate anything; the recipient of the null pointer will then not have to de-allocate anything.

Because Objects in .net do not require explicit deallocation, the performance advantages of regarding a null reference as an empty string no longer apply. Nonetheless, methods which are called from code that might expect behavior similar to that of COM methods will often regard null string references as being the same as empty strings.

Solution 3

You want

If Not String.IsNullOrEmpty(Request.Params("xxx") Then
    ...
End If

Or

if (!String.IsNullOrEmpty(Request.Params("xxx")) {
    ...
}
Share:
15,830
Aisah Hamzah
Author by

Aisah Hamzah

Creator of the .NET XSLT 3.0 processor Exselt, which is currently in beta. You can reach me via Twitter (sometimes), by mail at [email protected] (be careful not to look like spam), or through my companies Exselt or Abrasoft (consultancy). I'm an invited expert of the W3C XSLT and XQuery Working Group where we develop the next version of XSLT: version 3.0. Since September 2015 the group went public, which means that most of the mail discussions can now be actively participated in. If you find a bug or other issue with the XSLT 3.0 specification, you can send a mail to [email protected], or you can visit the archives (since Sept 2015).

Updated on June 13, 2022

Comments

  • Aisah Hamzah
    Aisah Hamzah almost 2 years

    In a mixed code project (VB and C#) we were debugging some old Visual Basic code like this:

    If Request.Params("xxx") <> "" Then
       'do something
    

    I considered this a bug as Request.Params could be null, in which case the statement would've become false which wasn't the idea.

    So I thought. I just found out -- again -- that VB's Nothing and C#'s null are not the same things and Nothing is not the same as null. In fact:

    if(String.Empty == null)          // in C# this is always false (correct)
    
    If String.Empty = Nothing Then    ' in VB this is always true (????)
    

    How is this even possible? Is this some backward compatibility issue?

  • Aisah Hamzah
    Aisah Hamzah almost 14 years
    Yes, likely. But that's not the question here... The question is why perceived (in)equality is not actual (in)equality in VB. Why Nothing is not null, while often it is.
  • Matt Mitchell
    Matt Mitchell almost 14 years
    Yeah just misread, still this helps avoid this problem. = in VB.NET is different from == as Jon Skeet clarifies (should be the accepted).
  • Aisah Hamzah
    Aisah Hamzah almost 14 years
    Yes, thanks, that I understand :). But the first part of your answer is intriguing. Equals should give a reference equals when compared to Nothing, should it not?
  • Aisah Hamzah
    Aisah Hamzah almost 14 years
    Ah, ignore my previous comment. You edited meanwhile. That's more like it, thanks for the reference. I'm not so happy with it either. Any (more) ideas on the "why" part? Sounds a lot like Perl: everything's a string until further notice.
  • Jon Skeet
    Jon Skeet almost 14 years
    @Abel: Which part - why they wanted to preserve compatibility with pre-.NET VB, or why pre-.NET VB had this kind of comparison?
  • Aisah Hamzah
    Aisah Hamzah almost 14 years
    @Jon: well, my thought was that MS did not want to preserve compability, which is why we still have millions of VB6 addicts out there. So, that brings us to why .NET VB should have this kind of comparison to begin with. Also, in .NET 4.0 Microsoft declared it would bring VB and C# closer. My guess is, they missed this one.
  • Jon Skeet
    Jon Skeet almost 14 years
    @Abel: It's far too late to change the behaviour now. They could have done it at the VB6 / VB7 point, but decided not to. They tried to preserve compatibility in many places, where they could. They don't particularly want people to use VB6 now, as far as I'm aware.
  • Damien_The_Unbeliever
    Damien_The_Unbeliever almost 14 years
    @Abel - For .NET 4.0, they've brought things closer in terms of access to functionality, not making the two languages identical but spelt differently - if they did that, why have two languages? But Nothing is a strange and magical beast in VB.Net - In generic code, it's sometimes closer to being default(T)
  • Aisah Hamzah
    Aisah Hamzah almost 14 years
    @Damian: that's a good comparison, thanks! @Jon: thanks for the update, I second your opinion :)
  • PauliL
    PauliL almost 14 years
    I think the main point is that in BASIC, string is not a pointer, it is just zero or more characters. Therefore it is not possible to compare to NULL.
  • Aisah Hamzah
    Aisah Hamzah almost 14 years
    Even in BASIC, string is a pointer, but it is hidden by the language. This is VB.NET, not BASIC. Pointers have become close to extinct in .NET (safe for some unsafe code) and have been replaced by references. Any language for .NET is bound to the CLR specification, which means a string is a reference type that is treated specially (i.e.: read-only).
  • Aisah Hamzah
    Aisah Hamzah over 12 years
    Interesting considerations and thoughts, esp. the comparison with COM. Thanks for adding it to this rather old question +1 ;)