C# 可为空<;int>;vs.int?-有什么区别吗?

C# 可为空<;int>;vs.int?-有什么区别吗?,c#,.net,C#,.net,显然,Nullable和int?在值上是等价的。有什么理由选择一个而不是另一个吗 Nullable<int> a = null; int? b = null; a == b; // this is true Nullable a=null; 智力?b=零; a==b;//这是真的 没有区别 int?只是Nullable的简写,它本身就是Nullable的简写 编译后的代码将与您选择使用的代码完全相同。表单只是完整类型的简写。个人偏好是选择其中一个的唯一原因 全部细节 语法T?是 N

显然,
Nullable
int?
在值上是等价的。有什么理由选择一个而不是另一个吗

Nullable<int> a = null;
int? b = null;
a == b; // this is true
Nullable a=null;
智力?b=零;
a==b;//这是真的
没有区别

int?
只是
Nullable
的简写,它本身就是
Nullable
的简写


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

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

全部细节

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


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

当实体包含声明如下的属性时:

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

EF generator属性将在相应的数据库表中生成一个带有可空字段的可空属性。

虽然我完全同意在大多数情况下它们是相同的,但我最近遇到了一种情况,即这两者之间存在差异。 有关血淋淋的详细信息,请参见,但这里给您一个快速示例:

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
}
如果您对这一点的确切原因感到好奇,我真的建议您检查已经存在的标记,但基本问题是在
(或
as
)运算符之后的解析阶段,当我们面对
标记时,我们检查下一个标记是否可以解释为一元运算符(
&
可以是一元运算符)如果是这样的话:解析器并不关心
标记是否是类型修饰符,它只是使用它前面的类型,并将解析其余的标记,就像
标记是三元运算符一样(因此解析将失败)


因此,虽然通常
int?
Nullable
是可互换的,但由于解析器如何看待代码,它们会产生完全不同的结果。Nullable是泛型类型,而int?则不是

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

例如:这里不能用int替换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;
      }
   }
}
类LazyValue,其中T:struct
{
私有可空val;
私有函数getValue;
//构造器。
公共懒散值(Func Func)
{
val=null;
getValue=func;
}
公共价值
{
得到
{
if(val==null)
//执行委托。
val=getValue();
返回(T)val;
}
}
}

这真的很不幸。这表明您在某个地方有一些其他的
可空
定义,因为使用内置的
可空
,EF不可能看到两者之间的差异。即使EF的人想以不同的方式对待他们,他们也做不到。有人证实了这一点吗?(只是因为反对票而有点谨慎)@RayL不,事实并非如此。这个答案是不正确的,正如hvd指出的,不可能。考虑到EF代码是使用代码模板生成的,这实际上是可能的。我的回答是基于我的经验和我建议的改变修复了我的问题。此外,似乎有些人发现,根据投票结果,情况确实如此。不幸的是,有些情况并非完全如此。见此。第一种情况,
test
,用括号固定,因此
var test=(a是int?)&b。也可以通过
var test=a is int?&&bb
是一个简单的值参数(对评估没有副作用),与
&
相比,更喜欢
&
似乎有些奇怪。在这种特殊的语法中,
是一个关键字符。请参阅链接的问题和答案,您的评论都在这里提到:)我刚刚在这里添加了这个信息,我觉得它是相关的,因为它指出了两种形式之间的区别,并且证明了它不仅仅是语法上的,sugarJeppe是正确的。它不是编译,因为它将
int?
解释为三元操作(
var test=a is int?:
),而不是可为空的int。@LeviFuller(续)请参阅文档了解这些特定的
bool
重载。它们是(用于
bool的
&
)和(用于
bool的
&
)。请注意,这些小节中的第一小节是如何清楚地命名为logical的。记住,在C#中,
bool
和数字类型之间没有转换(“强制转换”)!如果问题询问的是泛型类型,那么这可能很重要,但是问题指定了int,因此它不是
Nullable
而是
Nullable
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 ';'
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;
      }
   }
}