views:

165

answers:

2

This must've have been asked before but I couldn't locate it. In a mixed code project (VB and C#) we were debugging some old Visual Basic code where a statement as follows could be found:

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, -- probably for the tenth time and I will keep forgetting -- that the following two statements are not equal, while Nothing in VB should be equal to null in C# (thought I):

if(String.Empty == null)          // always false
If String.Empty = Nothing Then    ' always true

Should I dismiss this as a typical Microsoft backward compatibility effort, or should I consider this a huge error in the VB.NET compiler? Does anybody know the Microsoftean opinion on this oddity?

+1  A: 

You want

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

Or

if (!String.IsNullOrEmpty(Request.Params("xxx")) {
    ...
}
Graphain
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.
Abel
Yeah just misread, still this helps avoid this problem. = in VB.NET is different from == as Jon Skeet clarifies (should be the accepted).
Graphain
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.
PauliL
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).
Abel
+9  A: 

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.

Jon Skeet
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?
Abel
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.
Abel
@Abel: Which part - why they wanted to preserve compatibility with pre-.NET VB, or why pre-.NET VB had this kind of comparison?
Jon Skeet
@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.
Abel
@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.
Jon Skeet
@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)
Damien_The_Unbeliever
@Damian: that's a good comparison, thanks! @Jon: thanks for the update, I second your opinion :)
Abel