当你使用 Nullable Reference Type feature 时,你需要考虑,对于每个(参考)变量,该变量是否允许 null。
这与值类型没有什么不同,例如int。你不会做
int a = 5;
if (a != null) { /* ... */ }
因为 a 永远不能为空。您需要使用 int? 数据类型来甚至允许a 为空。
当然,有一些方法可以破坏 Nullable Reference Type 特性——比如忽略警告。
让我们获取您的代码并解决一些问题。我会添加行号。
1 List<Person> listPersons = (List<Person>)(await PService.GetPersons()).ToList();
2 Person oPerson = new Person();
3 if (listPersons != null){
4 oPerson = (Person)listPersons.Where(p => p.Name!.Equals(_Name)).FirstOrDefault();
5 }
6 if (oPerson != null) {
7 _UID_CUSTOMER = oPerson.UID_CUSTOMER;
8 }
1号线
await PService.GetPersons() 返回 IEnumerable<Person>。因为没有?,这意味着整个对象不能为空。此外,每个元素(流中的每个 Person 对象)都不能为空。如果你真的希望PService.GetPersons()给你数据或者null,返回类型将是Task<IEnumerable<Person>?>。
将 IEnumerable<Person> 转换为 List<Person> 是危险的。你得到一个IEnumerable<Person>,一个接口。底层集合可以是一个列表,或者它可以是一个数组,或者其他实现IEnumerable的东西。当 PService.GetPersons() 的实现发生变化时,将其转换为 List 可能会导致运行时错误。
跑ToList()没有多大意义后演员表。它已经是一个列表。事实上,假设您没有得到转换异常,如果 List 为空,此方法将抛出异常。这完全消除了进行空检查的意义。
所以,这是更好的第 1 行:
IEnumerable<Person> people = await PSService.GetPersons();
- 对“person”使用正确的复数形式。
- 保留类型
IEnumerable<Person>,如果您只打算使用一次流,则无需强制转换为列表。
2号线
您将 oPerson 的默认值设置为 Person 的新实例,并且数据类型 (Person) 表示它永远不能包含空值。但是,在第 4 行,您使用 FirstOrDefault,其中“默认”将为空。所以我们需要更改数据类型来解决这个问题。
此外,我们将重写第 4 行,使第 4 行始终运行,而第 2 行的变量初始化是不必要的。
事实上,这一整行都是需要的,因为它只是变量名。所以删除它。
3号线和5号线
检查listPersons(现在称为people)的可空性没有意义,因为您已经告诉编译器它不能为空。删除那些行。
4号线
在你有Name!.Equals()的地方。 ! 是“空宽恕”运算符。问题是如果Name一片空白,那么.Equals() 将抛出异常。将 .Equals 替换为 ==。 (这一切都假设Name 的数据类型是string?)。
最后的演员表也是不必要的。 FirstOrDefault 将返回 Person(实际上是 Person?),因此将其转换为相同的数据类型是一种浪费。
Person? oPerson = people.FirstOrDefault(p => p.Name == _Name);
旁注,我不同意将 FirstOrDefault 中的“默认”值设为 Person 的新实例。我的意见是FirstOrDefault的默认值应该是空的。这对我来说对您的代码具有语义意义。您正在查看列表以找到匹配的人。如果你找不到一个,那么你会得到 null,而不是一些新的空人。
第 6、7 和 8 行
这些很好。
但是,如果在执行这些行之前 _UID_CUSTOMER 的值已经为 null,则可以简化这些行。在这种情况下,所有行都可以替换为:
_UID_CUSTOMER = oPerson?.UID_CUSTOMER;
这表示:
- 如果 oPerson 为 null,则使用 null
- 如果 oPerson 不为空,则使用 UID_CUSTOMER 的值
同样,只有在执行此行之前您不关心 _UID_CUSTOMER 的值时,这才有效。如果你想覆盖_UID_CUSTOMER只要当oPerson 不为空时,将其改回 if 语句。
所以,把它们放在一起你会得到
IEnumerable<Person> people = await PSService.GetPersons();
Person? oPerson = people.FirstOrDefault(p => p.Name == _Name);
_UID_CUSTOMER = oPerson?.UID_CUSTOMER;