5

Possible Duplicate:
Bug?? If you assign a value to a nullable integer via a ternary operator, it can't become null

While this question may seem like a duplicate of many, it is actually being asked for a specific reason. Take this code, for example:

Dim n As Integer? = If(True, Nothing, 1)

In that code, the ternary expression should be returning Nothing, but it's setting n to 0. If this were C#, I could say default(int?) and it would work perfectly. Now it looks like I am going to have to ditch the ternary and use a regular If block, but I really want to use the ternary.

If Nothing were truly VB.NET's equivalent to C#'s default, how can you explain this behavior?

Community
  • 1
  • 1
oscilatingcretin
  • 10,457
  • 39
  • 119
  • 206
  • `Nothing` in this instance equates to `default(int)` because your inferred type based on the expression is `int`, not `int?`. This can be seen with `If(true, Nothing, new Integer?(1))` – Marc Apr 19 '12 at 18:58
  • So then it is safe to say that VB.NET *doesn't* have an equivalent of C#'s default. If it did, it could have used type inference to determine that Nothing, in this case, equates to a nullable integer's default value which is Nothing, not 0. – oscilatingcretin Apr 19 '12 at 19:02
  • In an indirect way, that's correct. In C#, the `default` takes a type, which can be used for inferrence. In VB, it seems that `Nothing` plays the passive role in this. – Marc Apr 19 '12 at 19:05
  • Wow, it IS a dupe! I vote to close. – oscilatingcretin Apr 19 '12 at 19:39

1 Answers1

6

The VB.NET equivalent to C#'s default is the keyword Nothing. The code you wrote should compile just fine so long as Id.Value returns an Integer value.

The reason your updated sample is going wrong is because of the nature of Nothing. In VB.NET Nothing is the empty value and it's convertible to any type. Now for an If expression, the compiler has to infer what the type of the return should be, and it does this by looking at the two value arguments.

The value Nothing has no type, but the literal 1 has the type Integer. Nothing is convertible to Integer so the compiler determines Integer is the best type here. This means when Nothing is chosen as the value, it will be interpreted as Integer and not Integer?.

The easiest way to fix this is to explicitly tell the compiler that you want 1 to be treated as an Integer?.

Dim n As Integer? = If(True, Nothing, CType(1, Integer?))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • In my question, am I using Nothing in the ternary expression correctly? If not, how would you modify it to do what I am trying? Have you, by any chance, attempted to reproduce the issue using your own code? – oscilatingcretin Apr 19 '12 at 18:49
  • @oscilatingcretin the code you're using is just fine. I wrote up a sample locally and it worked as expected – JaredPar Apr 19 '12 at 18:51
  • Okay then try the updated code I edited into my question. When you run that single line of code, `n` is being set to Nothing as expected? When I run it, it's being set to 0. – oscilatingcretin Apr 19 '12 at 18:54
  • @oscilatingcretin that's expected. For numeric types `Nothing` and `0` are interchangeable. It's best to read `Nothing` as the empty value of the type I'm using it with. For an `Integer` the empty value is `0`. – JaredPar Apr 19 '12 at 18:55
  • But for a nullable, it's Nothing. Notice that I am using a nullable and not a standard value type. – oscilatingcretin Apr 19 '12 at 18:58
  • @oscilatingcretin ok, I see where the current sample is going wrong. Give me a second and I'll update my answer – JaredPar Apr 19 '12 at 18:59
  • Ugh. In C#, I can go like `int? n = true ? default(int?) : 1;` without any hassle. Oh well, thanks for your help. Marked and upvoted. – oscilatingcretin Apr 19 '12 at 19:13
  • 1
    @oscilatingcretin it's a tradeoff scenario. In C# the `default(...)` expression includes a type hence it's explicit what type of value you want. In VB.Net though it's a typeless default value. Shorter to type out in most cases, more generally useful than say `null` but does have this corner case. – JaredPar Apr 19 '12 at 19:44