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

Dev*_*v X 1 c# linq nullreferenceexception

我基本上试图迭代大量数据并将返回的数据查询转换为视图模型中更有限的对象.

我没有做大量代码,而是在列表中调用.ForEach(),然后在视图模型列表中添加一个新条目.

这很好用,但是,有一个属性(Address)是可选的.

当我到达可选项时,NullReferenceException如果DB中的项目没有条目,我会得到.

代码示例是:

    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

    }));
Run Code Online (Sandbox Code Playgroud)

我从这个网站上的不同答案中发现,如果我更改地址行,它会显示:

        Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
Run Code Online (Sandbox Code Playgroud)

当我点击一个空条目时,代码现在可以工作了tmp.

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

另外,我不必这样做x.Address?.FirstLine?是因为这是一个字符串,字符串已经可以为空了吗?

Ale*_*ith 5

当您尝试访问父对象本身为null的属性时,会导致此特定情况下出现空引用异常.

x.Address.FirstLine
Run Code Online (Sandbox Code Playgroud)

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

它与您尝试设置的内容无关(即目标视图模型).

这是有效的原因:

x.Address?.FirstLine 
Run Code Online (Sandbox Code Playgroud)

..因为'在后台'它首先检查是否Address为null.如果不是,则返回FirstLine,如果是,则返回null.它在语义上等同于:

if (x.Address == null)
{
    return null;
}
else
{
    return x.Address.FirstLine;
}
Run Code Online (Sandbox Code Playgroud)

这是关于引入?的博客文章.C#中的运算符用于某些背景阅读:https://blogs.msdn.microsoft.com/jerrynixon/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator/