Nothing = String.Empty (Why are these equal?) - vb.net

Why does the first if statement evaluate to true? I know if I use "is" instead of "=" then it won't evaluate to true. If I replace String.Empty with "Foo" it doesn't evaluate to true. Both String.Empty and "Foo" have the same type of String, so why does one evaluate to true and the other doesn't?
//this evaluates to true
If Nothing = String.Empty Then
End If
//this evaluates to false
If Nothing = "Foo" Then
End If

Nothing in VB.net is the default value for a type. The language spec says in section 2.4.7:
Nothing is a special literal; it does not have a type and is convertible to all types in the type system, including type parameters. When converted to a particular type, it is the equivalent of the default value of that type.
So, when you test against String.Empty, Nothing is converted to a string, which has a length 0. The Is operator should be used for testing against Nothing, and String.Empty.Equals(Nothing) will also return false.

It's a special case of VB's = and <> operators.
The Language Specification states in Section 11.14:
When doing a string comparison, a null reference is equivalent to the string literal "".
If you are interested in further details, I have written an in-depth comparison of vbNullString, String.Empty, "" and Nothing in VB.NET here:
https://stackoverflow.com/a/34069187/87698

Related to this topic, if you use a string variable initialized with "nothing" to be assigned to the property "value" of a SqlParameter that parameter is ignored, not included in the command sent to the server, and a missing parameter error is thrown.
If you initialize that variable with string.empty everything goes fine.
//This doesn't work
Dim myString as String = nothing
mySqlCommand.Parameters.Add("#MyParameter", SqlDbType.Char).Value = myString
//This works
Dim myString as String = string.empty
mySqlCommand.Parameters.Add("#MyParameter", SqlDbType.Char).Value = myString

Try this:
Console.WriteLine("Is String.Empty equal to Nothing?: {0}", String.Empty.Equals(Nothing))
The = operator doesn't enforce equal types, whereas the .Equals() method of a string object does, as does the Is operator.

Related

if() operator/function bugs dealing with nothing. IF() doesn't return nothing. Why?

Most probable this is a bug reporting rather than asking question, however, if it's not so , and anyone knows why , please solve this paradox.
Function IF(arg1, arg2, arg3) isn't functioning in all circumstances as wisely described in MSDN. When arg2 is Nothing, it doesn't return Nothing in special cases, particularly, when arg1 is TRUE (arg2 is Nothing) and arg3 is not of nullable type. Instead it converts Nothing to arg3 type (sets defaults value of arg3 type for arg2) and passes that value to arg3. The beneath code illustrates that issue\question\bug
Comments imply the behavior, message titles help to follow (if sequence is lost)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'
Dim V As Integer?
Dim D As Boolean = True
MsgBox(Nothing, vbOK, "'1st msgbox") '1st msgbox
MsgBox(If(D, Nothing, True), vbOK, "'2nd msgbox.") '2nd msgbox. If(D, Nothing, True) returns false instead of nothing
MsgBox(If(True, Nothing, True), vbOK, "3rd the same as 2nd") '3rd the same as 2nd, shows no matter either we use boolean variable or type the value directly
V = If(D, Nothing, 15)
MsgBox(V, vbOK, "4th msgbox, shows the problem isn't related to messaging the IF()...") '4th msgbox, shows the problem isn't related to messaging the IF() directly, or first, assigning it to a variable, capable of holding null
MsgBox(If(True, Nothing, 15), vbOK, "5th.") ' 5th. this returns different result (int format) but again not the expected nothing
'Now how it works
MsgBox(If(True, Nothing, "some text"), vbOK, "6th") ' 6th 'NOW this returns [Nothing] as expected, (probably) because string is nullable
MsgBox(If(True, Nothing, "some text") Is Nothing, vbOK, "7th proof of...") '7th proof of above result. Really nothing not string.empty
Dim UnevaluatedPart As Nullable(Of Integer)
MsgBox(If(True, Nothing, UnevaluatedPart), vbOK, "8th. Now it returns nothing") ' 8th. Now it returns nothing with integer? as third argument (false part)
MsgBox(If(True, Nothing, UnevaluatedPart) Is Nothing, vbOK, "' 9th. Proof of above") ' 9th. Proof of above (it's really nothing not empty string ""
End Sub
The If operator can be thought of as being like a generic function:
If(Of T)(condition As Boolean,
truePart As T,
falsePart As T) As T
That means that the second and third arguments must be the same type (either explicitly or one can be cast as the other) and the return value will be that same type. With that in mind, let's look at some of your examples.
'2nd msgbox. If(D, Nothing, True) returns false instead of nothing
MsgBox(If(D, Nothing, True), vbOK, "'2nd msgbox.")
So, for that to work at all, the second and third as the same type. What type could that possibly be? The type of the second argument is unspecified while the type of the third is Boolean. Nothing can be cast as type Boolean so that's what happens, and the return value is thus also Boolean. Casting Nothing as type Boolean yields False, so the second argument is effectively False and that's what gets returned.
Dim UnevaluatedPart As Nullable(Of Integer)
' 8th. Now it returns nothing with integer? as third argument (false part)
MsgBox(If(True, Nothing, UnevaluatedPart), vbOK, "8th. Now it returns nothing")
' 9th. Proof of above (it's really nothing not empty string ""
MsgBox(If(True, Nothing, UnevaluatedPart) Is Nothing, vbOK, "' 9th. Proof of above")
In both these cases, the type of the second parameter is unspecified and the type of the third parameter is Integer? so Nothing gets cast as type Integer?. That means that both the second and third arguments are a Integer? with no value. You're going to get the same return value whether the condition is True or False. Of course it won't be an empty String because the return value MUST be type Integer?. It's not just Nothing though; it's a Integer? with no value, so you can actually test the HasValue property of that result.
' 5th. this returns different result (int format) but again not the expected nothing
MsgBox(If(True, Nothing, 15), vbOK, "5th.")
Again, the type of the second argument is unspecified so the argument and return type is inferred from the third argument. That third argument is type Integer so that means that Nothing is cast as type Integer, which yields zero. The condition is True so it is that zero value that gets returned. If you tested whether that was equal to Nothing then you'd find that it is, which is exactly why that's what Nothing got converted to for the second parameter.
In VB.NET Nothing has two meanings:
null(as in C#)
the default value of a given type (default in C#)
If you use the conditional operator with two types both must be convertible to each other. With Nothing and True it's possible because the default value of a Boolean is False.
So it's the same as the longer version
Dim bool1 As Boolean = Nothing ' False
Dim bool2 As Boolean = If(True, bool1, True)
bool2 will be False because bool1 is False because that's the default value of Boolean.
What you learn from this? Be careful with the If operator and implicit conversions and always remember that Nothing doesn't only mean null in VB.NET.
Also remember that value types like Boolean always have a value, they are never null. In this case Nothing really means "give me the default value".
Now an exercise :) What will be the result of the integer i here?
Dim i AS int32 = If(true, nothing, 777)
"If" needs a return value, when it looks at the parameter and see Nothing with a Boolean it says "Oh, I should return a Boolean". If you want to return a nullable Boolean, then one of the parameter need to be a Boolean?. Same with integer.
Dim a As Boolean? = If(True, Nothing, True)
Dim b As Boolean? = If(False, Nothing, True)
Dim c As Boolean? = If(True, Nothing, CType(True, Boolean?))
Dim d As Boolean? = If(False, Nothing, CType(True, Boolean?))
Console.WriteLine(a) ' false
Console.WriteLine(b) ' true
Console.WriteLine(c) ' empty
Console.WriteLine(d) ' true

VB.NET Nothing evaluating to False [duplicate]

Coming from Basic boolean logic in C#, I was wondering why:
Dim b As Boolean
Dim obj As Object = Nothing
'followig evaluates to False'
b = DirectCast(Nothing, Boolean)
'This throws an "Object reference not set to an instance of an object"-Exception'
b = DirectCast(obj, Boolean)
A CType(obj, Boolean) would evaluate to False(just as CBool(obj)). I think it is because the compiler uses a helper function, but that is not my theme.
Why does casting Nothing to Boolean evaluates to False, whereas casting an object that is Nothing to Boolean throws an Nullreference-Exception? Does that make sense?
[Option Strict ON]
Presumably, this is because Nothing in VB.NET is not exactly the same thing as null in C#.
In the case of value types, Nothing implies the default value of that type. In the case of a Boolean, the default value is False, so the cast succeeds.
One of the primary differences between value types such as Integer or structures and reference types such as Form or String is that reference types support a null value. That is to say, a reference type variable can contain the value Nothing, which means that the variable doesn't actually refer to a value. In contrast, a value type variable always contains a value. An Integer variable always contains a number, even if that number is zero. If you assign the value Nothing to a value type variable, the value type variable just gets assigned its default value (in the case of Integer, that default value is zero). There is no way in the current CLR to look at an Integer variable and determine whether it has never been assigned a value - the fact that it contains zero doesn't necessarily mean that it hasn't been assigned a value.
–The Truth about Nullable Types and VB...
EDIT: For further clarification, the reason the second example throws a NullReferenceException at run-time is because the CLR is attempting to unbox the Object (a reference type) to a Boolean. This fails, of course, because the object was initialized with a null reference (setting it equal to Nothing):
Dim obj As Object = Nothing
Remember that, as I explained above, the VB.NET keyword Nothing still works the same way as null in C# when it comes to reference types. That explains why you're getting a NullReferenceException because the object you're attempting to cast is literally a null reference. It does not contain a value at all, and therefore cannot be unboxed to a Boolean type.
You don't see the same behavior when you try to cast the keyword Nothing to a Boolean, i.e.:
Dim b As Boolean = DirectCast(Nothing, Boolean)
because the keyword Nothing (this time, in the case of value types) simply means "the default value of this type". In the case of a Boolean, that's False, so the cast is logical and straightforward.
There's a couple of things you have to realize here.
The first is what others have already pointed out: Nothing can be interpreted by the VB compiler as simply the Boolean value False given the proper context, such as Dim b As Boolean = Nothing.
This means that when the compiler sees this:
b = DirectCast(Nothing, Boolean)
It sees a literal (Nothing) and also sees that you want to use this literal as a Boolean. That makes it a no-brainer.
But now here's the second thing you have to realize. DirectCast on an Object is essentially an unboxing operation (for value types). So what needs to happen from the VB compiler's perspective is: there needs to be a Boolean in that box, or else the operation will fail. Since there is in fact nothing in the box—and this time we're really talking nothing, as in null—it throws an exception.
If I were to translate this code to C#, it would look like this:
bool b;
object obj = null;
b = (bool)default(bool);
b = (bool)obj;
Hopefully that makes things a bit clearer?
There's a difference between using the keyword (literal) Nothing, and using a reference variable whose value is Nothing.
In VB.NET, the literal (keyword) Nothing gets special treatment. The Nothing keyword can be automatically converted into a value type, using the default value of that type.
A reference variable whose value is Nothing is different. You don't get the special behaviour.
The documentation says DirectCast "requires an inheritance or implementation relationship between the data types of the two arguments".
Clearly Object does not inherit from or implement Boolean, unless you have put a boxed Boolean into an object variable.
So the code below fails at runtime with an exception.
Dim obj As Object = Nothing
b = DirectCast(obj, Boolean)
To get the expected behavior, you need this code:
Dim b As Boolean?
Dim obj As Object = Nothing
b = DirectCast(obj, Boolean?)
The character ? mean Nullable(of ).
I'm finding that comparing of the Boolean variable to a string of "True", "False" or Is nothing seems to ensure that I get the correct comparisons. I was using a function to return an html string of a div with an image of a checked or unchecked radio button and was having the issue of nothing coming back as false. Using the variable = "True" or "False" string and doing the last check with IS NOTHING helped to resolve that issue.
Dim b as boolean = nothing
response.write CheckValue(b = "True")
response.write (b = "False")
response.write (b is nothing)
Function CheckValue(inVal as boolean) as string
if inVal then
return ("<div><img src="checked.png" ></div>
else
return ("<div><img src="unchecked.png" ></div>
end if
end function
The system seems to do the conversion to string when implicitly compared to a string whereas using the .tostring method just creates an error while allowing the last comparison to actually compare to a value of nothing.
Hopefully that helps somewhat. It at least let me

Differences between "" and vbnullstring [duplicate]

All of these
txtUsername.Text <> vbNullString
txtUsername.Text <> String.Empty
txtUsername.Text <> ""
seem to return the same result. So, what's the difference between vbNullString, String.Empty and ""?
What's the difference?
String.Empty and "" both represent a string of length zero.
Contrary to the documentation, which claims that vbNullString "[r]epresents a zero-length string", vbNullString is actually Nothing (null in C#, see Reference Source).
(Note that this only applies to VB.NET! The situation is different in VBA, see below for details.)
So how do I check if a string is null/Nothing or empty?
Contrary to what the other answer says, you do not need to use String.IsNullOrEmpty to check for Nothing or an empty string, since the = operator in Visual Basic treats Nothing and an empty string as equivalent. Thus, the idiomatic way to check for "null or empty string" in VB.NET is to simply use = "":
Dim s As String = Nothing
If s = "" Then Console.WriteLine("YES") ' Prints YES
Thus, Not String.IsNullOrEmpty(s), s <> "", s <> String.Empty and s <> vbNullString are all equivalent. I prefer the concise s <> "", but it's mainly a question of preference and style.
Does that mean that I can use an empty string and Nothing interchangeably?
In general: no. This equivalence of an empty string and Nothing is only true for VB.NET's built-in = and <> operators as well as most of the methods in the Microsoft.VisualBasic namespace (Len(...), Trim(...), ...). Once you go into pure .NET territory (for example, by using methods from the rest of the Base Class Library), Nothing and the empty string are treated differently:
Dim sNothing As String = Nothing
Dim sEmpty As String = ""
Console.WriteLine(sEmpty = sNothing) ' True
Console.WriteLine(sEmpty.Equals(sNothing)) ' False
Console.WriteLine(String.Equals(sEmpty, sNothing)) ' False
Console.WriteLine(Len(sEmpty)) ' 0
Console.WriteLine(Len(sNothing)) ' 0
Console.WriteLine(sEmpty.Length) ' 0
Console.WriteLine(sNothing.Length) ' throws a NullReferenceException
Why is vbNullString defined as Nothing instead of ""?
Backwards compatibility. In VBA (and "VB Classic"), vbNullString could be used to get a "null string reference"¹. Within VBA, vbNullString was treated like the empty string "", but when interacting with non-VB-code, vbNullString was mapped to the NULL pointer and "" was mapped to an empty string.
When using PInvoke in VB.NET, Nothing is mapped to the NULL pointer and "" is mapped to an empty string, so it makes sense to have the legacy constant vbNullString equal Nothing in VB.NET.
¹ which is completely different from VBA's Null and Empty, which are special Variant subtypes, and VBA's Nothing, which, in VBA, only applies to objects and not to strings.
vbNullString is a constant, more likely out of VB6, String.Empty and "" are the same, some say that there is a performance difference, but that is not true, it is your choice what you use.
To check whether a string is empty you can use If String.IsNullOrEmpty(String). The advantage is that it will also check for null, because string is a class and because of this a reference type.
If are going to insert values to MS-SQL database and if column doesn't allows null(Not null) then strValue=vbNullString will generate exception but strValue="" will insert blank spaces.

Visual Basic .NET Empty/Null String difference?

I would like to differentiate between NULL and "".
How do I determine with an if statement if a String is NULL or ""?
Nothing is when the string variable has no instance it refers to at all while "" is when the string variable has something it refers to and it is an empty string.
To distinguish, you could put the following conditions:
Dim s As String
If s Is Nothing Then 'It means it is Nothing
End If
If s = "" Then 'It means it points to some instance whose value is empty string
End If
VB.Net also has String.Empty which is equivalent to "":
If s = String.Empty Then
End If
"" is just an empty string, but it is still initialized and has an allocated position in the memory as a string with no characters.
Null or Nothing is a string that has not been initialized or defined, which means that there is no memory is allocated for this, thus the string technically doesn't exist.
To check if a string is null you'd do:
If str Is Nothing Then
To check if a string is empty you could do:
If str = "" Then
or:
If str.Length = 0 Then
However, to check if it's either null or empty, you get use of the String.IsNullOrEmpty() method:
If String.IsNullOrEmpty(str) Then
you can get dbnulll error if string come from database
you can determine it with
isdbnull(str)
Pass your string variable into this function to test for both:
String.IsNullOrEmpty(s)
You can test for null like this:
s Is Nothing
You can test if it is an empty string like this:
s = String.Empty
The accepted answer and the others are all partially wrong because they do not address a crucial point of empty strings in VB. According to the documentation:
For strings in Visual Basic, the empty string equals Nothing. Therefore, "" = Nothing is true.
This means that MyString = String.Empty will be true when MyString Is Nothing is also true. So you definitely want to test against Nothing before testing against String.Empty (or "").

What is the difference between vbNullString, String.Empty and ""?

All of these
txtUsername.Text <> vbNullString
txtUsername.Text <> String.Empty
txtUsername.Text <> ""
seem to return the same result. So, what's the difference between vbNullString, String.Empty and ""?
What's the difference?
String.Empty and "" both represent a string of length zero.
Contrary to the documentation, which claims that vbNullString "[r]epresents a zero-length string", vbNullString is actually Nothing (null in C#, see Reference Source).
(Note that this only applies to VB.NET! The situation is different in VBA, see below for details.)
So how do I check if a string is null/Nothing or empty?
Contrary to what the other answer says, you do not need to use String.IsNullOrEmpty to check for Nothing or an empty string, since the = operator in Visual Basic treats Nothing and an empty string as equivalent. Thus, the idiomatic way to check for "null or empty string" in VB.NET is to simply use = "":
Dim s As String = Nothing
If s = "" Then Console.WriteLine("YES") ' Prints YES
Thus, Not String.IsNullOrEmpty(s), s <> "", s <> String.Empty and s <> vbNullString are all equivalent. I prefer the concise s <> "", but it's mainly a question of preference and style.
Does that mean that I can use an empty string and Nothing interchangeably?
In general: no. This equivalence of an empty string and Nothing is only true for VB.NET's built-in = and <> operators as well as most of the methods in the Microsoft.VisualBasic namespace (Len(...), Trim(...), ...). Once you go into pure .NET territory (for example, by using methods from the rest of the Base Class Library), Nothing and the empty string are treated differently:
Dim sNothing As String = Nothing
Dim sEmpty As String = ""
Console.WriteLine(sEmpty = sNothing) ' True
Console.WriteLine(sEmpty.Equals(sNothing)) ' False
Console.WriteLine(String.Equals(sEmpty, sNothing)) ' False
Console.WriteLine(Len(sEmpty)) ' 0
Console.WriteLine(Len(sNothing)) ' 0
Console.WriteLine(sEmpty.Length) ' 0
Console.WriteLine(sNothing.Length) ' throws a NullReferenceException
Why is vbNullString defined as Nothing instead of ""?
Backwards compatibility. In VBA (and "VB Classic"), vbNullString could be used to get a "null string reference"¹. Within VBA, vbNullString was treated like the empty string "", but when interacting with non-VB-code, vbNullString was mapped to the NULL pointer and "" was mapped to an empty string.
When using PInvoke in VB.NET, Nothing is mapped to the NULL pointer and "" is mapped to an empty string, so it makes sense to have the legacy constant vbNullString equal Nothing in VB.NET.
¹ which is completely different from VBA's Null and Empty, which are special Variant subtypes, and VBA's Nothing, which, in VBA, only applies to objects and not to strings.
vbNullString is a constant, more likely out of VB6, String.Empty and "" are the same, some say that there is a performance difference, but that is not true, it is your choice what you use.
To check whether a string is empty you can use If String.IsNullOrEmpty(String). The advantage is that it will also check for null, because string is a class and because of this a reference type.
If are going to insert values to MS-SQL database and if column doesn't allows null(Not null) then strValue=vbNullString will generate exception but strValue="" will insert blank spaces.