110

Apparently Nullable<int> and int? are equivalent in value. Are there any reasons to choose one over the other?

Nullable<int> a = null;
int? b = null;
a == b; // this is true
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Zachary Scott
  • 20,968
  • 35
  • 123
  • 205

5 Answers5

159

No difference.

int? is just shorthand for Nullable<int>, which itself is shorthand for Nullable<Int32>.

Compiled code will be exactly the same whichever one you choose to use.

LukeH
  • 263,068
  • 57
  • 365
  • 409
  • 3
    Unfortunately there are some corner cases when this is not strictly true. See this [answer](http://stackoverflow.com/a/24738380/1552016). – qqbenq Jul 14 '14 at 14:07
28

While I completely agree that in most cases they are the same, I recently came across a situation, when there is a difference between those two. For the gory details see this question, but to give you a quick example here:

// compiles happily
void Test<T>(T a, bool b)
{
    var test = a is Nullable<int> & b;
}

Change Nullable<int> to int? (and nothing else):

//does not compile
void Test<T>(T a, bool b)
{
    var test = a is int? & b;
}

This second version gives the following error messages:

error CS1003: Syntax error, ':' expected 
error CS1525: Invalid expression term ';'

If you are curious about the exact reason for this, I really recommend you to check the already linked question, but the basic problem is that in the parsing phase after an is (or an as) operator, when we face a ? token we check if the next token can be interpreted as a unary operator (& could be one) and if so: the parser doesn't care about the possibility of the ? token being a type modifier, it simply uses the type before it, and will parse the rest as if the ? token were a ternary operator (thus the parsing will fail).

So, while in general int? and Nullable<int> are interchangeable, there are some corner cases when they produce completely different results, because of how the parser sees your code.

qqbenq
  • 10,220
  • 4
  • 40
  • 45
  • 3
    The first case, `test`, is fixed with a parenthesis, so `var test = (a is int?) & b;`. Can also be fixed with `var test = a is int? && b;`, and given that `b` is a simple value parameter (no side effects on evaluation) it seems strange to prefer `&` over `&&`. – Jeppe Stig Nielsen Jul 14 '14 at 14:09
  • 1
    In that particular syntax, `?` is a key character. – Pete Garafano Jul 14 '14 at 14:09
  • See the linked question and answer, your comments are all addressed there :) I just added this info here, as I felt it is relevant, as it brings out a difference between the two forms, and proves that it is not just syntactic sugar – qqbenq Jul 14 '14 at 14:10
  • 1
    Jeppe is correct. It's not compiling because it is interpreting `int?` as a ternary operation (`var test = a is int? : `), not a nullable int. – Levi Fuller Aug 13 '15 at 19:50
  • 1
    Also @Jeppe... `&` is a bitwise AND while `&&` is the logical operator. For instance, it evaluates the result bit-for-bit... ( == ) `1 == 01` & `2 == 10`... `(1 & 2) == 0` – Levi Fuller Aug 13 '15 at 20:09
  • @LeviFuller: Yes - as the answer already stated - that the `?` token is interpreted as a ternary operator in the first case, my point was that the two forms of nullable types are not always freely interchangeable, because of how parsing of the language works. Also it has nothing to do with the difference between logical and bitwise and operators, but depends on if the operator can be interpreted as a unary one. It is really explained [here](http://stackoverflow.com/questions/24305290/type-modifer-precedence-vs-logical-and-operator-vs-address-of-operator) – qqbenq Aug 14 '15 at 09:29
  • @LeviFuller (to your last comment) That is not really correct/relevant in C# which is a type-safe language in which a `bool` is a separate type which is not a numeric type. In particular, if the compile-time operands (left-hand side and right-hand side of the operator) are of a numeric type, only `&` exists (no overload of `&&` applies). So your remark makes no sense there. On the other hands, if both operands are of compile-time type `bool`, specific overloads for that are defined by the language. Both the `operator &(bool, bool)` and the operator `&&(bool, bool)` are "logical" not "bitwise". – Jeppe Stig Nielsen Aug 14 '15 at 10:38
  • 1
    @LeviFuller _(continued)_ See the documentation for these particular `bool` overloads. These are [Boolean logical operators](https://msdn.microsoft.com/en-us/library/aa691309.aspx) (the `&` for `bool`) and [Boolean conditional logical operators](https://msdn.microsoft.com/en-us/library/aa691311.aspx) (the `&&` for `bool`). Note how the first of these subsections is clearly named **logical**. Remember, in C# there are no conversions ("casts") between `bool` and numeric types! – Jeppe Stig Nielsen Aug 14 '15 at 10:41
  • 1
    What if you use " var test = a is (int?) & b; " ? – Rodrigo May 04 '16 at 13:01
  • I guess we can say: "they are identical, except if you are writing a code generator; then there is a difference between `int?` or `Nullable` because of how they are parsed". – fernacolo Dec 20 '20 at 04:42
24

The ? form is just a shorthand for the full type. Personal preference is the only reason to choose one over the other.

Full details here.

The syntax T? is shorthand for Nullable<T>, where T is a value type. The two forms are interchangeable.

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140
7

There apparently is a difference between the two when using code-first Entity Framework (EF) generation:

When your entity contains a property declared like:

public class MyEntity
{
    public Nullable<int> MyNullableInt { get; set; } 
}

EF will not generate a nullable property and you will have to force the generator to make it nullable like so:

public class YourContext : DbContext
{
    public DbSet<MyEntity> MyEntities{ get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<MyEntity>().Property(x => x.MyNullableInt).IsOptional();
    }
}

On the other hand, if you declare your entity like:

public class MyEntity
{
     public int? MyNullableInt { get; set; }
}

the EF generator will property generate a nullable property with a nullable field in the corresponding database table.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Maciej
  • 2,175
  • 1
  • 18
  • 29
  • 2
    That's really unfortunate. – siride Jun 05 '13 at 22:28
  • 10
    That suggests you have some other `Nullable` definition somewhere, because with the built-in `Nullable`, it's not possible for EF to see the difference between the two. Even if the EF folks wanted to treat them differently, they couldn't. –  Jun 05 '13 at 22:36
  • 1
    Has someone confirmed this is the case? ( just a little cautious because of the negative votes) – RayLoveless Jan 17 '14 at 12:51
  • @RayL No this isn't the case. This answer is not correct and as hvd pointed out, impossible. – jamesSampica May 20 '14 at 17:58
  • 1
    Considering that EF code is generated using code templates, this may in fact be possible. My answer is based on my experience and the change I suggested fixed the issue I was having. Also, it seems like some people found that it is indeed the case based on the up-votes. – Maciej Jun 24 '14 at 15:15
2

Nullable is a generic type, but int? is not.

There are some scenarios where Nullable should be used over int?

for eg: here you cannot replace Nullable with int?

how can you change the below code without using Nullable?

class LazyValue<T> where T : struct
{
   private Nullable<T> val;
   private Func<T> getValue;

   // Constructor.
   public LazyValue(Func<T> func)
   {
      val = null;
      getValue = func;
   }

   public T Value
   {
      get
      {
         if (val == null)
            // Execute the delegate.
            val = getValue();
         return (T)val;
      }
   }
}
Rajes
  • 1,036
  • 10
  • 15
  • 3
    Which might matter if the question was asking about generic types, but the question has specified int, so it's not `Nullable` it's `Nullable` – Andrew Feb 16 '17 at 20:15