Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary operator VB vs C#: why resolves Nothing to zero?

I just shoot myself in the foot and would like to know whether there were actual reasons to make this situation possible.
And anyway, this question can stay for the convenience of the future foot shooters.


Suppose we have a nullable value in vb.net:

Dim i as Integer?

We want to assign a value to it, basing on a condition, and using a ternary operator, because it's so neat and stuff:

i = If(condition(), Nothing, 42)

That is, if a condition is true, employ the nullability, otherwise the value.
At which point the shooting occurs. For no apparent reason VB compiler decides that the common base type for Nothing and Integer is Integer, at which point it silently translates the statement to:

i = If(condition(), 0, 42)

Now, if you were to do this in C#:

i = (condition()) ? null : 42;

You would immediately get a compiler error saying that <null> doesn't mix well with int. Which is great, as my foot would have been healthier had I went the C# way this time. And for this to compile, you have to explicitly write:

i = (condition()) ? null : (int?)42;

Now, you can do the same in VB and get the correct null-ness you would expect:

i = If(condition(), Nothing, CType(42, Integer?))

But that requires having your foot shot in the first place. There's no compiler error and there's no warning. That's with Explicit On and Strict On.


So my question is, why?
Should I take this as a compiler bug?
Or can someone explain why the compiler behaves this way?

like image 514
GSerg Avatar asked Nov 10 '10 17:11

GSerg


People also ask

Why ternary operator is better than if-else?

Emphasis: value-selection before/after action needing values. There's a different emphasis: An if / else statement emphasises the branching first and what's to be done is secondary, while a ternary operator emphasises what's to be done over the selection of the values to do it with.

What is ternary operator in VB net?

The general syntax of the Ternary operator in VB.NET. If(question, expression1, expression2) Here question(?) is the condition if condition is true, then expression1 will be execute otherwise expression2 will be execute. The general syntax of the Ternary operator in C#.NET.

Does C have ternary operator?

We use the ternary operator in C to run one code when the condition is true and another code when the condition is false. For example, (age >= 18) ? printf("Can Vote") : printf("Cannot Vote");

Is ternary operator faster than if C#?

Ternary Operator: 5986 milliseconds or 0.00000005986 seconds per each operator. If-Else: 5667 milliseconds or 0.00000005667 seconds per each statement.


4 Answers

This is because VB's Nothing is not a direct equivalent to C#'s null.

For example, in C# this code will not compile:

int i = null;

But this VB.Net code works just fine:

Dim i As Integer = Nothing

VB.Net's Nothing is actually a closer match for C#'s default(T) expression.

like image 92
Joel Coehoorn Avatar answered Oct 09 '22 03:10

Joel Coehoorn


The ternary operator can only return one type.

In C#, it tries to choose a type based on null and 42. Well, null doesn't have a type, so it decides that the return type of the ternary operator is that of 42; a plain old int. Then it complains because you can't return null as a plain old int. When you coerce 42 as a int?, the ternary operator is going to return an int?, so null's valid.

Now, I don't know about VB, but quoting from the MSDN,
Assigning Nothing to a variable sets it to the default value for its declared type.

Which, since VB determines that the ternary operator will return an int (using the same process C# did), Nothing is 0. Again, coercing the 42 to be an int? turns Nothing into the default value of int?, which is null, as you expected.

like image 31
Naelin Avatar answered Oct 09 '22 04:10

Naelin


I am thinking this has something more to do with IF than with Nothing. Consider this code:

''#     This raises an exception
Dim x As Integer?
x = If(True, Nothing, Nothing)
MessageBox.Show(x.Value)

''#     As does 
Dim x As Integer?
x = Nothing
MessageBox.Show(x.Value)

''#     Changing one of the truthpart arguments of If is what seems to return the zero.
Dim x As Integer?
x = If(True, Nothing, 5)
MessageBox.Show(x.Value)

Why it is doing this I still don't know, probably a question for the VB team. I don't think it has to do with the Nothing keyword or Nullable.

like image 2
Mike Cheel Avatar answered Oct 09 '22 04:10

Mike Cheel


Nothing and null are not the same thing... from the MSDN:

Assigning Nothing to a variable sets it to the default value for its declared type.

Also

If you supply a value type in Expression, IsNothing always returns False.

Keep in mind that int? is a nullable type, but it's still a value type, not a reference type.

Try setting it to DbNull.Value instead of Nothing...

like image 2
James King Avatar answered Oct 09 '22 03:10

James King