空合并运算符与 value()
Posted
技术标签:
【中文标题】空合并运算符与 value()【英文标题】:Null coalescing operator vs. value() 【发布时间】:2015-03-27 12:17:43 【问题描述】:我正在创建一些对象以通过 API 返回到表单,这些对象是从数据库值派生的,包括在数据库中可能为空但在我的 API 上下文中不能为空的值(我正在获取数据来自多个表,所以我知道如果一个表中的字段为空,我可以从另一个表中获取合法值):
List<ResultsByLineShiftSlot> returnResults = new List<ResultsByLineShiftSlot>();
foreach (LineShiftSlot ls in db.LineShiftSlots.OrderBy(ls => ls.ScheduledDateAndTime).Where(ls => ls.ProductionDate == slotDate &&
ls.ShiftId == shiftId &&
ls.LineId == lineId &&
ls.Quantity > 0 &&
ls.BlendId != null))
var recordedResult = db.LineShiftSlotResults.FirstOrDefault(r => r.LineShiftSlotId == ls.Id);
if (recordedResult != null)
ResultsByLineShiftSlot returnResult = new ResultsByLineShiftSlot
BlendId = recordedResult.BlendId
;
else
ResultsByLineShiftSlot returnResult = new ResultsByLineShiftSlot
BlendId = ls.BlendId ?? 0
;
return returnResults;
在上面的例子中,BlendId 在 LineShiftSlots 中可以为 null,但在 LineShiftSlotResults 中不能。
在已知可空变量包含非空值的上下文中,哪个更好?
我是否应该使用空合并运算符:
BlendId = ls.BlendId ?? 0
或者我应该使用 .Value():
BlendId = ls.BlendId.value()
两者都可以编译,并且似乎可以工作。
在这种情况下,它们在功能上是否相同?使用其中一种是更好的做法吗?我知道 .value() 可能会返回异常,而 null 合并运算符不能,但在这种情况下 .value 永远不能为空。
【问题讨论】:
为什么不只是labelId = recordValue.labelId ?? otherValue
?但是一般来说,如果您“知道”该值不是空值,则应该使用.Value
,因为如果您的断言错误,则会引发异常,而空值合并运算符将隐藏该事实并默默地给您错误的值.
如果您确定FirstOrDefault
将返回一个值,请使用First
,否则您还应检查recordValue
是否为null
。
如果您要使用Value
,我建议您将其与HasValue
配对,而不是null
比较。
@crashmstr 记录集在我的实际代码中可能为空,也可能不为空(稍后我会添加一个更好的示例)。记录集是否为空决定了我将使用哪个源来填充返回对象。
@Lee 如果记录集为空,那么我从不同的数据源中提取。我添加了一个更完整的示例来说明。使用.Value
来引发错误的要点是我要问的要点,尽管在if (someValue != null) nullableVariable = someValue.Value();
的简化示例中显然永远不会触发该特定异常。
【参考方案1】:
在一般情况下,它们在语义上并不等价。
labelId = recordValue.labelId.Value;
这个意思是我知道这个值不能是null
。如果我的假设是错误的就扔掉。
另一方面,
labelId = recordValue.labelId ?? 0;
labelId = recordValue.labelId.GetValueOrDefault();
这两个表示值可能为null,如果发生这种情况,忽略它,认为它是正常的,并将其替换为默认值。
在这种情况下,我会使用GetValueOrDefault()
,这样会更明显一些(JIT 会内联此方法)。
但是,您的代码等效于这个更简单的替代方案:
labelId = recordValue.labelId ?? otherValue;
【讨论】:
【参考方案2】:在这种情况下,代码将是相同的,但是您是否考虑过以下内容
labelId = recordValue.labelId ?? otherValue
本质上是这样的
if(recordValue.labelId != null)
labelId = recordValue.labelId.Value;
else
labelId = otherValue;
【讨论】:
以上是关于空合并运算符与 value()的主要内容,如果未能解决你的问题,请参考以下文章