【问题标题】:Nullable<int> vs. int? - Is there any difference?Nullable<int> 与 int? - 有什么不同吗?
【发布时间】:2010-10-26 23:14:52
【问题描述】:

显然Nullable&lt;int&gt;int? 在价值上是等价的。有什么理由选择其中一个吗?

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

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    没有区别。

    int? 只是Nullable&lt;int&gt; 的简写,它本身就是Nullable&lt;Int32&gt; 的简写。

    无论您选择使用哪一个,编译后的代码都将完全相同。

    【讨论】:

    • 不幸的是,有些极端情况并非严格如此。看到这个answer
    【解决方案2】:

    虽然我完全同意在大多数情况下它们是相同的,但我最近遇到了一种情况,这两者之间存在 差异。 有关血腥细节,请参阅this question,但在这里给你一个简单的例子:

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

    Nullable&lt;int&gt; 更改为int?(仅此而已):

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

    第二个版本给出以下错误消息:

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

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

    因此,虽然int?Nullable&lt;int&gt; 通常可以互换,但在某些极端情况下,它们会产生完全不同的结果,因为解析器如何看待您的代码。

    【讨论】:

    • 第一种情况,test,用括号固定,所以var test = (a is int?) &amp; b;。也可以用var test = a is int? &amp;&amp; b; 修复,鉴于b 是一个简单的值参数(对评估没有副作用),更喜欢&amp; 而不是&amp;&amp; 似乎很奇怪。
    • 在该特定语法中,? 是一个关键字符。
    • Jeppe 是正确的。它没有编译,因为它将 int? 解释为三元运算 (var test = a is int? &lt;return if true&gt; : &lt;return if false&gt;),而不是可为空的 int。
    • 另外@Jeppe...&amp; 是按位与,而&amp;&amp; 是逻辑运算符。例如,它逐位计算结果... ( == ) 1 == 01 & 2 == 10... (1 &amp; 2) == 0
    • @LeviFuller (续)请参阅这些特定 bool 重载的文档。它们是Boolean logical operators&amp; 代表bool)和Boolean conditional logical operators&amp;&amp; 代表bool)。请注意这些小节中的第一个是如何明确命名为 logical 的。请记住,在 C# 中,bool 和数字类型之间没有转换(“强制转换”)!
    【解决方案3】:

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

    详细信息here

    语法T?Nullable&lt;T&gt;,其中T 是一个值类型。 这两种形式可以互换。

    【讨论】:

      【解决方案4】:

      在使用代码优先实体框架 (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 生成器将在相应的数据库表中生成一个可以为空的属性,其中包含一个可以为空的字段。

      【讨论】:

      • 这真的很不幸。
      • 这表明您在某处还有一些其他的Nullable 定义,因为使用内置的Nullable&lt;T&gt;,EF 不可能看到两者之间的区别。即使 EF 的人想以不同的方式对待他们,他们也做不到。
      • 有人确认是这种情况吗? (只是因为反对票有点谨慎)
      • @RayL 不,事实并非如此。这个答案不正确,正如 hvd 指出的那样,不可能。
      • 考虑到 EF 代码是使用代码模板生成的,这实际上是可能的。我的回答是基于我的经验和我建议的更改解决了我遇到的问题。此外,似乎有些人根据赞成票发现情况确实如此。
      【解决方案5】:

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

      【讨论】:

      • 如果问题是关于泛型类型,但问题指定了 int,这可能很重要,所以它不是 Nullable&lt;T&gt; 它是 Nullable&lt;int&gt;
      猜你喜欢
      • 2012-06-14
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 2020-10-25
      • 1970-01-01
      相关资源
      最近更新 更多