C# 在c中访问可空值的最佳方法#

C# 在c中访问可空值的最佳方法#,c#,nhibernate,nullable,hibernate-criteria,C#,Nhibernate,Nullable,Hibernate Criteria,在我们的C#代码中,我们已经在尝试访问变量之前测试了它是否为null if (myInt.HasValue) { var yourInt = myInt; // do something with yourInt } 我的问题是:如果在测试之后没有使用null属性,那么使用null属性与下面的方法有什么区别吗 if (myInt.HasValue) { var yourInt = myInt.Value; // see the difference? // do somet

在我们的C#代码中,我们已经在尝试访问变量之前测试了它是否为null

if (myInt.HasValue) {
  var yourInt = myInt;

  // do something with yourInt
}
我的问题是:如果在测试之后没有使用null属性,那么使用null属性与下面的方法有什么区别吗

if (myInt.HasValue) {
  var yourInt = myInt.Value; // see the difference?

  // do something with yourInt
}
这仅仅是一个偏好问题,还是使用
.Value
有明显的原因或性能影响,即使在可为空的对象通过了该测试之后

更新

我扩展了我的第二个示例,我们已经使用
HasValue
进行了测试,但是在那里我们使用
.Value
来访问值

更新2

我将示例更新为使用
var
s,因为在我们的代码中,我们实际上没有使用
int
类型,很抱歉这个糟糕的示例。在我们的代码中,我们实际上只是在NHibernate条件查询中使用对象-
Expression.Eq(“thing”,myInt)
query

这不会引发编译错误。我试图简化这个例子,在不涉及NHibernate的情况下找到问题的根源。抱歉,如果这使某些答案无效。我只是想看看,如果我们强制另一个方法查找值,而不是显式调用
.value
,是否会影响性能

这只是一个偏好的问题,还是有明显的原因

如果
HasValue
false
将抛出

因此,如果您不想经历
invalidoOperationException
s,请先选中
HasValue

注意

int yourInt = myInt;
不合法(编译时失败),因为没有从
int?
int
的隐式转换(如果值为
null
;没有将
int?
转换为的合理值)。你可以说:

int yourInt = (int)myInt;
请注意,如果
myInt
null
,这将抛出,就像访问
Value
一样

最后一点,如果您同意接受默认值,可以使用并说:

这相当于:

int yourInt;
if(myInt.HasValue) {
    yourInt = myInt.Value;
}
else {
    yourInt = defaultValue;
}
这不会引发编译错误。我试图简化这个例子,在不涉及NHibernate的情况下找到问题的根源。抱歉,如果这使某些答案无效。我只是想看看,如果我们强制另一个方法查找值,而不是显式调用.value,是否会影响性能

不。性能在这里是完全无关的,尤其是当涉及到数据库时。这绝对不会有任何有意义的性能差异,也肯定不会成为瓶颈。只需编写最清晰的代码。坦白地说,我发现
.Value
是最清晰的。

此代码无效:

if (myInt.HasValue) {
  int yourInt = myInt;

  // do something with yourInt
}
如果不想使用
Value
属性,则必须改用显式强制转换,或空合并运算符,或
GetValueOrDefault
,例如

int yourInt = (int) myInt;
强制转换最终被编译为访问
属性IIRC


因此,是的,即使在您测试了一个值是否为非null之后,您仍然需要做一些事情来将其转换为基础值——只是为了让它进行编译。编译器不会尝试分析“可能为空”(例如,假设它是一个实例变量,它可能会因访问之间的线程化而改变)。它只是遵循允许对可空表达式执行的操作规则,而隐式转换为不可为null的类型并不是允许您执行的操作之一…

有一个原因可以解释为什么您不能直接调用
.Value
direct:当
myInt
为null时,您希望
yourInt
的值是什么

如果希望将其设置为默认值(例如:0),可以在可为null的int上创建一个extensionmethod,如
.ValueOrDefault()

更新:此问题已解决。在2013年12月晚些时候和1月初,我将继续对此优化进行更多思考。谢谢你的提问


我只是想看看,如果我们强制另一个方法查找值,而不是显式调用.value,是否会影响性能

首先,如果你有一个性能问题,那么你是唯一能回答这个问题的人,你可以用秒表尝试两种方法,看看哪一种更快。对我来说,这是一个谜,为什么人们经常在StackOverflow上问这个问题。这就像说“嘿,互联网,这是两匹马的照片。哪一匹跑得更快?”我们怎么知道呢与它们赛跑,然后你就会知道。它们是你的马

第二,你在一般意义上问了一个错误的问题。问题不应该是“对性能有影响吗?”,而应该是“对性能有不可接受的影响吗?”同样,我们不知道什么是您可以接受的,什么是您不能接受的

第三,你在一个非常具体的意义上问了一个错误的问题。如果您对纳米级优化感兴趣,这里要问的正确问题是,使用值getter或GetValueOrDefault方法哪个更快

答案是GetValuerDefault方法通常比Value快。为什么?因为区别在于:

if (this.HasValue) return this.value; else throw new Exception();

有什么区别抖动很可能不会与前一种方法内联,因此您需要支付几纳秒以内的
罚款,以进行间接调用


如果几纳秒的损失与您有关,那么(1)祝贺您编写了一个仅在几微秒内运行的程序,并且(2)您需要非常仔细地测量,以查看是否有任何真正的差异,因为纳秒非常小。

如果(myInt!=null){…},您还可以编写
If(myInt!=null){…}
。我发现这比使用
HasValue
属性更清楚。感谢您的回复。我在回答问题时更新了我的问题
int yourInt = (int) myInt;
if (this.HasValue) return this.value; else throw new Exception();
return this.value;