空结合运算符与值()

时间:2015-01-28 14:39:03

标签: c# null-coalescing-operator

我正在创建一些通过API返回表单的对象,这些对象是从数据库值派生的,包括数据库中可能为null的值,但在我的API上下文中不能为null(我正在获取来自多个表的数据,所以我知道如果一个表中的字段为空,我可以从另一个表中获取合法的值):

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永远不能为null。

2 个答案:

答案 0 :(得分:1)

在一般情况下,它们在语义上不相同。

labelId = recordValue.labelId.Value;

这意味着我知道价值不能是null。如果我的假设错了,就扔掉

另一方面,

labelId = recordValue.labelId ?? 0;
labelId = recordValue.labelId.GetValueOrDefault();

这两个意味着值可能为空,如果发生这种情况,请忽略它,考虑它是正常的,并用默认值替换它。

在这种情况下,我会使用GetValueOrDefault(),这会让它更明显(JIT将内联此方法)。


但是,您的代码等同于这个更简单的替代方法:

labelId = recordValue.labelId ?? otherValue;

答案 1 :(得分:0)

在这种情况下,代码将是相同的,但是您考虑了以下

labelId = recordValue.labelId ?? otherValue

基本上是以下

if(recordValue.labelId != null){
    labelId = recordValue.labelId.Value;
}
else
{
    labelId = otherValue;
}