为什么在映射到null类型和从null类型映射时,null不会导致NullReferenceException?

时间:2019-01-20 21:45:47

标签: c# linq nullreferenceexception

我基本上是在尝试遍历大量数据,并将返回的数据查询转换为视图模型内更有限的对象。

而不是编写大量代码,我在列表上调用.ForEach(),然后将新条目添加到视图模型的列表中。

这很好用,但是有一个属性(地址)是可选的。

到达可选项目时,如果数据库中的项目没有条目,则会得到NullReferenceException

一个代码示例是:

    var tmp = _context.Person.Include(x => x.Address).ToList();

    tmp.ForEach(x => vm.List.Add(new IndexListItem()
    {
        Name = x.Name,
        Address = x.Address.FirstLine + " " + x.Address.SecondLine,
        ID = x.ID

    }));

此后,我从该站点的另一个答案中发现,如果我更改地址行,使其显示为:

        Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,

当我在tmp中输入一个空条目时,该代码即可正常工作。

我不理解这是因为tmp上的Address属性已经允许空值,而视图模型上的Address属性已经允许空值,所以,为什么更改行突然不返回错误?

此外,我不必做x.Address?.FirstLine?的原因是因为这是一个字符串,并且字符串已经可以为空吗?

4 个答案:

答案 0 :(得分:5)

在这种特殊情况下,当您尝试访问父对象本身为null的属性时,将导致null引用异常

x.Address.FirstLine

即在您的情况下,地址为空。

这与您要设置的内容(即目标视图模型)无关。

这有效的原因:

x.Address?.FirstLine 

..是因为“在后台”首先检查Address是否为空。如果不是,则返回FirstLine;如果不是,则返回null。在语义上等效于:

if (x.Address == null)
{
    return null;
}
else
{
    return x.Address.FirstLine;
}

这是有关?的介绍的博客文章。 C#中的运算符以了解一些背景知识:https://blogs.msdn.microsoft.com/jerrynixon/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator/

答案 1 :(得分:2)

  

我不明白这是因为tmp上的Address属性已经允许空值,而视图模型上的Address属性已经允许空值,所以,为什么更改行突然不返回错误?

您正在混合保存数据和加载数据。将数据保存到数据库时,out <- boxplot.stats(train$TEAM_FIELDING_E)$out train %>% mutate(TEAM_FIELDING_E = if_else(TEAM_FIELDING_E %in% out, mean(TEAM_FIELDING_E[!(TEAM_FIELDING_E %in% out)]), TEAM_FIELDING_E)) 是可以接受的,但是当您尝试使用数据时,null是不可接受的。

null conditional运算符(null)允许您“缩短” ?.语句,这类似于:

if

虽然与您的问题无关,但是您使用的代码效率极低,当您可以直接从数据库中获取这些属性时,您正在加载2个表以获取一些属性:

Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,

string Address = "";
if (x.Address != null)
{
    Address += x.Address.FirstLine;
}
// ....

答案 2 :(得分:2)

x.Address?.FirstLine,其中?是null传播运算符,这意味着如果x.Addressnull,请为null设置FirstLine

无效传播等效代码

if (x.Address == null)
   return null
else 
   return x.Address.FirstLine

所有引用类型变量都可以为空。因此,将null分配给引用类型始终有效。

string是您的示例中的引用类型。因此不会出现错误,因为string x = null有效

答案 3 :(得分:1)

您的问题不是Address为空,而是试图将其分配给另一个允许null的属性,而是您试图以空值访问.FirstLine。 / p>

如果Address为空,那么您要使用的.FirstLine等效于null.FirstLine,这是行不通的。没有什么不能容纳东西。

您正在使用的?表示法仅会影响Address,基本上是说Address是否 NOT null给我{{ 1}},如果它为null,请给我null。