【问题标题】:Null coalescing operator vs. value()空合并运算符与 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(); } 的简化示例中显然永远不会触发该特定异常。

标签: c# null-coalescing-operator


【解决方案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;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-09-19
      • 2011-03-16
      • 2019-03-01
      • 1970-01-01
      • 2013-09-13
      • 2023-03-23
      • 2012-09-23
      • 1970-01-01
      • 2011-02-20
      相关资源
      最近更新 更多