Nullable <int>与int? - 有什么区别吗?</int>

时间:2010-10-26 23:14:53

标签: c# .net

显然Nullable<int>int?的价值相同。有没有理由选择其中一个?

Nullable<int> a = null;
int? b = null;
a == b; // this is true

5 个答案:

答案 0 :(得分:120)

没有区别。

int?只是Nullable<int>的简写,Nullable<Int32>本身就是{{1}}的简写。

编译代码与您选择使用的代码完全相同。

答案 1 :(得分:21)

?表单只是完整类型的简写。个人偏好是选择其中一种的唯一原因。

完整详情here

  

语法T?是简写   Nullable<T>,其中T是值类型。   这两种形式是可以互换的。

答案 2 :(得分:17)

虽然我完全同意在大多数情况下它们是相同的,但我最近遇到了一种情况,当 这两者之间存在差异时。 有关血淋淋的详细信息,请参阅this question,但请在此处为您提供一个快速示例:

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

第一行提供以下错误消息:

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

如果您对此确切原因感到好奇,我建议您检查已经linked question,但基本问题是在is之后的解析阶段(或{{} 1}}}运算符,当我们面对as令牌时,我们检查 next 令牌是否可以解释为一元运算符(?可以如果是这样的话:解析器不关心&令牌是类型修饰符的可能性,它只是使用它之前的类型,并将解析其余的就像? token是一个三元运算符(因此解析将失败)。

因此,虽然一般?int?是可以互换的,但是由于解析器看到你的代码的结果,它们产生完全不同的结果时会出现一些极端情况。

答案 3 :(得分:6)

当使用代码优先的实体框架(EF)生成时,两者之间显然存在差异:

当您的实体包含声明为:

的属性时
public class MyEntity
{
    public Nullable<int> MyNullableInt { get; set; } 
}

EF不会生成可为空的属性,您必须强制生成器使其可以为空:

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();
    }
}

另一方面,如果您将实体声明为:

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

EF生成器将使用相应数据库表中的可空字段生成可为空的属性。

答案 4 :(得分:1)

Nullable 是一种通用类型,但 int?不是。

在某些情况下, Nullable 应该用于 int?

例如:在这里你不能用 int替换 Nullable

如何在不使用 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;
      }
   }
}