提问人:Dev X 提问时间:1/21/2019 最后编辑:Camilo TerevintoDev X 更新时间:1/21/2019 访问量:314
为什么 null 在映射到 null 类型和从 null 类型映射时不会导致 NullReferenceException?
Why doesn't a null cause a NullReferenceException when mapping to and from a null type?
问:
我基本上是在尝试遍历大量数据,并将返回的数据查询转换为视图模型中更有限的对象。
我没有做一大段代码,而是调用 .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
我不明白这一点,因为 上的 Address 属性已经允许 null,而视图模型上的 Address 属性允许 null,那么,为什么更改行突然不返回错误?tmp
此外,我不必这样做的原因是因为这是一个字符串并且字符串已经可以为空吗?x.Address?.FirstLine?
答:
在此特定情况下,当您尝试访问父对象本身为 null 的属性时,会导致 null 引用异常。
x.Address.FirstLine
即,在您的情况下,地址为空。
它与您尝试设置的内容(即目标视图模型)无关。
这样做的原因:
x.Address?.FirstLine
..是因为“在后台”它首先检查是否为 null。如果不是,则返回,如果是,则返回 null。它在语义上等同于:Address
FirstLine
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/
评论
您的问题不是 null 并且您正在尝试将其分配给另一个允许 null 的属性,而是您尝试访问为 null 的内容。Address
.FirstLine
如果为 null,那么您尝试执行的操作等同于不起作用。没有什么能容纳不住的东西。Address
.FirstLine
null.FirstLine
您使用的有效符号仅有效,基本上是说如果不是 null 给我的值,如果它是 null,则给我 null。?
Address
Address
.FirstLine
我不明白这一点,因为 tmp 上的 Address 属性已经允许 null,而视图模型上的 Address 属性允许 null,那么,为什么更改行突然不返回错误?
您将保存数据与加载数据混为一谈。当您将数据保存到数据库时,是可以接受的,但当您尝试使用数据时,则不可接受。null
null
null 条件运算符 () 允许您“缩短”语句,它类似于:?.
if
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
string Address = "";
if (x.Address != null)
{
Address += x.Address.FirstLine;
}
// ....
此外,虽然与您的问题无关,但您使用的代码非常无效,您正在加载 2 个表来获取几个属性,而您可以直接从数据库中获取这些属性:
var vm = _context.Person
.Select(x => new IndexListItem
{
Name = x.Name,
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
ID = x.ID
})
.ToList();
评论
?
x.Address?.FirstLine
其中 是 null 传播运算符,这意味着如果为 设置了 .?
x.Address
null
null
FirstLine
空传播等效代码
if (x.Address == null)
return null
else
return x.Address.FirstLine
所有引用类型变量都可以为 null。因此,将 null 分配给引用类型始终有效。
string
是示例中的引用类型。因此,您不会收到错误,因为是有效的string x = null
评论
null