空合并运算符与 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()的主要内容,如果未能解决你的问题,请参考以下文章

如何将 collasce null 运算符与 DbNull.Value 一起使用?

C#语法糖空合并运算符??和空合并赋值运算符 ??=

F#中的空合并运算符?

可能重载空合并运算符?

空合并运算符是不是有“对立面”? (……任何语言?)

VB.NET 空合并运算符? [复制]