17

How is C# NULL different from vb.net Nothing?

Console.WriteLine(Nothing = "") => True

vs

Console.WriteLine(null==""); => False

My understanding was that both null and Nothing are same. But above code clearly explains it is not.

What is the equivalent of C# null in VB.NET?

BetterLateThanNever
  • 886
  • 1
  • 9
  • 31
  • This question is off topic because it will result in opinions... – Trevor May 26 '17 at 01:10
  • @Blackwood it's close but it doesn't answer "What is the equivalent of `null` in VB.NET?" Also related: [Nothing vs null](http://blog.slaks.net/2010/12/nothing-vs-null.html). As far as I know VB.NET does not have an equivalent to C#'s `null`. – jrh May 26 '17 at 01:15
  • 4
    @Codexer I'm not sure how this could be primarily opinion based, the meaning of [`Nothing`](https://learn.microsoft.com/en-us/dotnet/articles/visual-basic/language-reference/nothing) and [`null`](https://learn.microsoft.com/en-us/dotnet/articles/csharp/language-reference/keywords/null) is very precisely defined. – jrh May 26 '17 at 01:22
  • @jrh If `Nothing` is more like `default` I would expect `Nothing = ""` to be false since `string` is a reference type, unless it isn't in VB.Net. – juharr May 26 '17 at 01:28
  • @juharr `String` is a reference type in VB.NET, the `String` class is exactly the same as `string` in C#. `String` and `string` are just aliases of `System.String` (like `int`, `System.Int32`, and `Integer`). I'm honestly somewhat curious to hear a language lawyer sort of answer on what the difference is between `Nothing` and `default`, `Nothing` seems to be a combination of `null` and `default`. – jrh May 26 '17 at 01:29
  • @jrh - Bingo on the the combination of the 2; it all depends on if it is reference, value, or nullable value. The types stay the same across all of the CLR languages; and the all of the CLR types (String, Int32) are just aliased in C# (as string, int) and VB (String, Integer). – Mad Myche May 26 '17 at 02:26
  • 1
    Reddy are you looking for an **exact** equivalent of C#'s `null` in VB.NET or are you just looking for something **similar to `null`** (i.e., `Nothing`)? Please update your post to clarify so there's only one question here. – jrh May 26 '17 at 22:21
  • @jrh I'm trying to find both the difference and equivalent of C#'s null in VB.Net . I might be violating rules of this community by asking two questions in one post. But, I just want to get a clear picture of what is what. – BetterLateThanNever May 30 '17 at 18:40

4 Answers4

12

You have chosen little bid complicated example to test difference between Nothing in vb.net and null in c#

From Visual basic language specification about Nothing:

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.

If you read description of default value expressions from Microsoft documentation you will notice that Nothing in vb.net and default(T) in C# have similar behaviour.

For example

Dim isSomething As Boolean = Nothing ' = False
Dim amount As Integer = Nothing ' = 0
Dim value As String = Nothing ' = null (notice not empty string!)

As prove that default value for string is not empty string, as many of comments/answers here stays

Dim value As String = Nothing
If value.Equals("") Then ' will throw NullReferenceException

End If 

Comparing Nothing to empty string "" with "=" operator is special case for vb.net, because Nothing for string will evaluate to null

From Visual basic language specification about relational operators for type String:

The operators return the result of comparing the two values using either a binary comparison or a text comparison. The comparison used is determined by the compilation environment and the Option Compare statement. A binary comparison determines whether the numeric Unicode value of each character in each string is the same. A text comparison does a Unicode text comparison based on the current culture in use on the .NET Framework. When doing a string comparison, a null reference is equivalent to the string literal "".

For checking string equality in vb.net you should use String.Equals method or Is operator.

Based on above language specifications

My understanding was that both null and Nothing are same. But above code clearly explains it is not.

They are not same, Nothing in vb.net is equivalent to default(T) in C#

What is the equivalent of C# null in VB.NET?

In C# you cannot set null to value types, so for reference types (String) equivalent for C# null in vb.net will be Nothing.
For example (null == default(String))

Fabio
  • 31,528
  • 4
  • 33
  • 72
  • 2
    This is the answer which clearly states that VB 'Nothing' and C# 'null' are different concepts. The concepts are only identical when applied to reference types. – Dave Doknjas May 26 '17 at 14:45
  • This answer is incorrect. The default value for variables is assigned automatically in VB when you declare them and give them no value. For example, the default value for number types is `0`, for Boolean is `false`, and so on. How on earth the default value for those is `Nothing`? This is different from C# which does not initialize the variables automatically for you and you get a warning if you try to use them before you assign a value. Read the accepted answer for the correct explanation. – Racil Hilan Nov 14 '17 at 22:46
  • @RacilHilan, `Nothing` **is** default value for any data type. – Fabio Nov 15 '17 at 01:38
  • Alright then, could you please add a link to MSDN that clearly shows that `Nothing` is the default value for any data type in VB? For my comment above, here is the MSDN for [Integer](https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/data-types/integer-data-type) and [Boolean](https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/data-types/boolean-data-type), notice the default value stated in the remarks. The only exception is the `String` type for a reason that any good developer should know. – Racil Hilan Nov 15 '17 at 03:07
  • In fact, here is an [MSDN](https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/nothing) that clearly states the opposite: **In Visual Basic, if you set a variable of a non-nullable value type to `Nothing`, the variable is set to the default value for its declared type.**, so obviously `Nothing` is **NOT** the default value of data types (except `String`). – Racil Hilan Nov 15 '17 at 04:14
  • @RacilHilan - from documentation: _"Nothing" represents the default value of any data type_ – Fabio Nov 15 '17 at 05:22
  • "Represents" and "is" are completely two different things. Continue reading the paragraph and the note below to understand what it means. "Represents" means that it is used as a syntax shortcut to assign the default value to any data type as demonstrated by your examples, but it is **NOT** the default value itself and can never be. How can you store `Nothing` in a non-nullable `Integer`? In fact, your examples will still work and give identical results if you remove `= Nothing` because VB automatically initializes variables unlike C#. – Racil Hilan Nov 15 '17 at 06:12
  • This is a basic concept in VB. In this context, `Nothing` is equivalent to `default(T)` in C#. For example, your first line is equivalent to the C# `int number = default(int);`. But we cannot say that `default(T)` is the default value for data types in C#. We can say it represents the default value. – Racil Hilan Nov 15 '17 at 06:21
  • @RacilHilan, nice "nitpicking" comments ;) – Fabio Nov 15 '17 at 10:31
  • @RacilHilan Do note, String is immutable, but technically it _is_ a reference type, not a primitive type. So contrary to popular belief, it's not an exception at all. It acts like all other reference types and gets null as default. – Nyerguds Nov 15 '17 at 11:14
  • @RacilHilan, here is the link to documentation that states that `Nothing` represents default value of any type [Nothing (Visual Basic)](https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/nothing) – Fabio Nov 15 '17 at 12:09
  • @Nyerguds Yes, that's obvious. As I said *"for a reason that any good developer should know"*. By exception, I meant exception among the data types, because `String` is considered data type by the MSDN, although it is actually a reference type as you mentioned. However, that's not *contrary to popular belief* as you mentioned, every good programmer must know that. That's why I didn't bother explaining it, but thanks for the clarification :) – Racil Hilan Nov 15 '17 at 14:36
  • It is not "nitpicking". Your original answer was completely wrong, and your updated answer is full of errors. To many errors to count, and you used some of my comments incorrectly. `Nothing` is equivalent to `null` in C#, whether we like it or not. It is only a language syntax that they used the same keyword to be like `default(T)` in the context of assignment (and only in this context). It is similar to the `=` operator in VB is used for comparison and assignment. When used for comparison, it is the same as the `==` operator in C#. Please learn VB before you post such amount of incorrect info – Racil Hilan Nov 15 '17 at 14:48
  • @RacilHilan, please point to the errors in the answer, I will be glad to correct an answer. – Fabio Nov 15 '17 at 15:25
  • Too many to put in a comment. I posted them as an answer. You can have a look if interested. The most important one is: `Nothing` is not always equivalent to `default(T)`, it is actually equivalent to `null` in some cases. It is a keyword with dual usage just like the `=` operator. It's confusing and poor syntax, but we have to live with it. – Racil Hilan Nov 15 '17 at 20:42
  • Notice: according to Microsoft Docs (https://learn.microsoft.com/en-us/dotnet/api/system.string.intern) you should NOT use reference comparison, like the "Is"-operator, to compare strings, regardless if it's VB.NET or C#. It is not always the case that a string reference to the same string value is the same reference. It depends on whether the string is interned or not. ;-) To be on the safe side, you should follow the best practices on this Microsoft Docs page when comparing strings: https://learn.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings – 2-Lee Feb 28 '22 at 05:03
11

In your code, VB guesses that you are comparing Strings, since one of the operands is a String. In String comparisons, Nothing is equivalent to the empty String "". It then does a value comparison, which returns True.

Use Is to compare references:

Console.WriteLine(Nothing Is "") '=> False
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
SSS
  • 4,807
  • 1
  • 23
  • 44
  • 1
    Although your answer is correct, I don't think the first two sentences are correct. I don't think that the `=` Operator does anything except conversion. It's VB itself that converts one operand to match the other operand's type if they're not of the same type. C# does that too in some cases, not in the case at hand (`Nothing = ""`), but for example if one operand is `Single` and the other one is `Double`. I updated your answer to remove the first incorrect two lines. You can roll it back if you disagree. – Racil Hilan Nov 15 '17 at 03:23
  • 1
    @RacilHilan yes, you are correct. I checked using ILDASM and VB = operator is the same as C# == operator (op_Equality) – SSS Nov 15 '17 at 03:55
  • 1
    Actually, I spoke a bit too soon. There is also an IL function `Microsoft.VisualBasic.CompilerServices.Operators::CompareObjectEqual`. (see https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.compilerservices.operators.compareobjectequal(v=vs.110).aspx But I think it's complicated enough that your edit is a good one – SSS Nov 15 '17 at 04:04
  • _This yields the default value of a String, which is an empty String ""_ - is not true. Default value of `String` is `null`. – Fabio Nov 15 '17 at 12:06
  • @Fabio Now that is "nitpicking" :). Of course you're right, because `String` is actually a reference. Thank you for the comment, I will update the answer accordingly. I hope SSS is OK with that. – Racil Hilan Nov 15 '17 at 14:55
2

The final version of the accepted answer correctly answers the question. However, Fabio added some useful information to his answer, but it has a number of incorrect information and concepts. So this answer is an attempt to merge the two answers in a more complete one with the correct information.

First of all, Nothing in VB is equivalent to null in C#, so your understanding of that is correct, at least partially (because that's only one use of the Nothing keyword). It's been reflected throughout the MSDN literature, although it's been fading recently and being replaced with the word null in many comments. Your confusion arises from the behavior and features of VB which differ from C# and programmers who are coming from other languages and not experienced in VB get confused by the results.

As stated in the accepted answer, the question is considered a string comparison by VB because one of the operands is a string. In string comparisons, VB treats Nothing the same as the empty string "" as per MSDN:

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

Now, why is that happening in VB? It happens because VB uses the Nothing keyword for two different things (similar to how it uses the = operator for two different things, assignment and comparison). The first usage is equivalent to null in C# as I mentioned above. The second usage is equivalent to the default(T) operator in C#. Like with the = operator, VB knows which way to use Nothing depending on the context. Examples:

In this line, VB uses Nothing as null:

Console.WriteLine(s Is Nothing) //C#: (s == null)

In these lines, VB uses Nothing as default(T) to assign the default value to the variable:

Dim s As String = Nothing //C#: string s = default(string);
Dim i As Integer = Nothing //C#: int i = default(int);

Finally, when comparing variables of different types, both VB and C# convert one operand to match the type of the other operand. For example, if you compare double and integer values. Both VB and C# will return true for this line:

Console.WriteLine(5.0 = 5) //C#: (5.0 == 5)

However, VB and C# differ in what types can be converted to what. Also, the empty string "" and null are treated the same in string comparisons in VB, but not in C#. This makes things easier in most cases, which is something known about VB in general. So you can easily test if your string has no value like this:

Console.WriteLine(s = Nothing)
Console.WriteLine(s = "")

Both lines will return the same result because VB treats Nothing as "" for comparison. In C#, you cannot do that and you have to test for both like this:

Console.WriteLine(s == null && s == "")

Obviously, VB is easier and shorter than C# in this case which is the most common one. However, this comes at the cost of losing some control. In the less common cases when you only want to test for null reference, C# become obviously better because you can still use the == operator:

Console.WriteLine(s == null)

While in VB, you cannot use the = operator and you have to use another one, the Is operator:

Console.WriteLine(s Is Nothing)

Also although VB is easier in the previous point, C# is clearer. That's why from code clarity perspective, this line can be used instead in both languages with the same result:

Console.WriteLine(string.IsNullOrEmpty(s))
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
  • I'm not sure about the `Default(T)` bit. If you disassemble `Dim s As String = Nothing`, the emitted IL sets `s` to a null reference as you would expect (`ldnull`, `stloc.0`). It is only at comparison time when it gets converted to empty string via `Microsoft.VisualBasic.CompilerServices.Operators::CompareObjectEqual`. – SSS Nov 16 '17 at 22:46
  • @SSS Yes, string comparison of `Nothing` and empty string `""` is a special case in VB and has nothing to do with `default(T)`. In such comparisons, `Nothing` is actually like `null`. So your answer in its final state is the good answer to the question. I only wanted to add some useful info about some other special cases in VB, like treating `Nothing` as `default(T)` during assignments and automatic conversions which confuses people into thinking that `Nothing` is not `null`. In fact it is `null` and the `default(T)` behavior is a secondary usage. – Racil Hilan Nov 24 '17 at 23:13
1

Nothing in VB varies by the objects type: - Reference types equate to null - Value types equate to the default value; which for a nullable type is null

Mad Myche
  • 1,075
  • 1
  • 7
  • 15