[英]Dereference of a possibly null reference ... Can my code be simplified?
My project is.Net-6 Blazor WebAssembly (hosted) in C#.我的项目是 C# 中的.Net-6 Blazor WebAssembly(托管)。 Can my code be simplified to avoid nullable warnings?可以简化我的代码以避免可空警告吗? I want the person's customer-ID in a page variable from the ApplicationUser object's Identity Name (variable is '_Name').我希望该人的客户 ID 在来自 ApplicationUser 对象的身份名称(变量是“_Name”)的页面变量中。 Thanks.谢谢。
List<Person> listPersons = (List<Person>)(await PService.GetPersons()).ToList();
Person oPerson = new Person();
if (listPersons != null){
oPerson = (Person)listPersons.Where(p => p.Name!.Equals(_Name)).FirstOrDefault();
}
if (oPerson != null) {
_UID_CUSTOMER = oPerson.UID_CUSTOMER;
}
When you work with the Nullable Reference Type feature , you need to consider, for every (reference) variable , whether that variable allows a null.当您使用可空引用类型功能时,您需要考虑,对于每个(引用)变量,该变量是否允许 null。
This is no different than value types, such as int
.这与值类型没有什么不同,例如int
。 You wouldn't do你不会做
int a = 5;
if (a != null) { // ... }
because a
can never be null.因为a
永远不可能是 null。 You'd need to use the int?
你需要使用int?
datatype to even allow a
to be null.数据类型甚至允许a
null。
Granted, there are way to break the Nullable Reference Type feature - such as ignoring warnings.当然,有办法打破 Nullable Reference Type 功能 - 例如忽略警告。
Let's take your code and fix some problems.让我们使用您的代码并解决一些问题。 I'll add line numbers.我将添加行号。
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 }
await PService.GetPersons()
returns an IEnumerable<Person>
. await PService.GetPersons()
返回一个IEnumerable<Person>
。 Because there's no ?
因为没有?
, that means that the whole object cannot be null. ,这意味着整个 object 不能是 null。 In addition, each element (each Person object within the stream) cannot be null.此外,每个元素(流中的每个 Person object)不能是 null。 If you really expect PService.GetPersons()
to give you data or null, the return type would be Task<IEnumerable<Person>?>
.如果您真的希望PService.GetPersons()
为您提供数据或null,则返回类型将为Task<IEnumerable<Person>?>
。
The cast of the IEnumerable<Person>
into a List<Person>
is dangerous.将IEnumerable<Person>
转换为List<Person>
是危险的。 You get an IEnumerable<Person>
, an interface.你得到一个IEnumerable<Person>
,一个接口。 The underlying collection could be a List, or it could be an Array, or something else that implements IEnumerable
.底层集合可以是一个列表,也可以是一个数组,或者其他实现IEnumerable
的东西。 Casting it to a List can lead to runtime errors when the implementation of PService.GetPersons()
changes.当PService.GetPersons()
的实现发生变化时,将其转换为 List 可能会导致运行时错误。
There's not much point of running ToList()
after the cast to a List.在转换为列表之后运行ToList()
没有多大意义。 It's already a list.已经是清单了。 In fact, assuming you didn't get a cast exception, this method would through an exception if the List was null.实际上,假设您没有遇到强制转换异常,如果 List 为 null,此方法将通过异常。 This eliminates the point of doing a null check at all.这完全消除了进行 null 检查的意义。
So, here's a better Line 1:所以,这是一个更好的第 1 行:
IEnumerable<Person> people = await PSService.GetPersons();
IEnumerable<Person>
, no need to cast to List if you're only going to use the stream once.保留类型IEnumerable<Person>
,如果您只打算使用一次 stream ,则无需转换为 List 。You set the default of oPerson
to a new instance of a Person, and the datatype ( Person
) says that it can never hold a null value.您将oPerson
的默认值设置为 Person 的新实例,并且数据类型 ( Person
) 表示它永远不能保存 null 值。 However, on line 4, you use FirstOrDefault
, which the "Default" will be null.但是,在第 4 行,您使用FirstOrDefault
,“默认”将为 null。 So we need to change the datatype to account for that.所以我们需要改变数据类型来解决这个问题。
In addition, we're going to rewrite line 4 so that line 4 always runs, and the initialization of the variable on line 2 is unnecessary.此外,我们将重写第 4 行,使第 4 行始终运行,并且不需要在第 2 行初始化变量。
In fact, this whole line is unneeded, because it would just be the varaible name.事实上,这整行是不需要的,因为它只是变量名。 So remove it.所以删除它。
There's no point in checking the nullability of listPersons
(now called people
), because you've told the compiler that it can't be null.检查listPersons
(现在称为people
)的可空性没有意义,因为您已经告诉编译器它不能是 null。 Remove those lines.删除这些行。
Inside the Where you have Name..Equals()
.在 Where you have Name..Equals()
中。 The !
!
is the "null forgiveness" operator.是“零宽恕”运算符。 Problem with that is that if Name
is null , then .Equals()
will throw an exception.问题在于,如果Name
是 null ,那么.Equals()
将引发异常。 Replace .Equals
with ==
.将.Equals
替换为==
。 (This is all assuming that the datatype of Name
is a string?
). (这都是假设Name
的数据类型是string?
)。
The cast at the end is also unnecessary.最后的演员阵容也是不必要的。 FirstOrDefault
will return a Person
(or null), so casting it to the same data type is wasteful. FirstOrDefault
将返回一个Person
(或 null),因此将其转换为相同的数据类型是浪费的。
Person? oPerson = people.FirstOrDefault(p => p.Name == _Name);
Side note, I don't agree with making the "default" value from FirstOrDefault
a new instance of Person.旁注,我不同意将FirstOrDefault
中的“默认”值设为 Person 的新实例。 My opinion is that FirstOrDefault
's default should be null.我的观点是FirstOrDefault
的默认值应该是 null。 This to me makes semantic sense for your code.对我来说,这对您的代码具有语义意义。 You're looking through a list to find a matching person.您正在查看列表以查找匹配的人。 If you can't find one, then you get null, not some new empty person.如果你找不到一个,那么你会得到 null,而不是一些新的空人。
These are fine.这些都很好。
However, you could simplify the lines if the value of _UID_CUSTOMER
was already null before executing these lines.但是,如果_UID_CUSTOMER
的值在执行这些行之前已经是 null,则可以简化这些行。 In that case, all the lines could be replaced with:在这种情况下,所有行都可以替换为:
_UID_CUSTOMER = oPerson?.UID_CUSTOMER;
This means:这表示:
Again, this only works if you didn't care about the value of _UID_CUSTOMER
before this line executes.同样,仅当您在执行此行之前不关心_UID_CUSTOMER
的值时,这才有效。 If you only want to overwrite _UID_CUSTOMER
only when oPerson
is not null, change it back to the if statement.如果只想在oPerson
不是 null 时覆盖_UID_CUSTOMER
,请将其改回 if 语句。
So, putting it all together you get所以,把它们放在一起,你会得到
IEnumerable<Person> people = await PSService.GetPersons();
Person? oPerson = people.FirstOrDefault(p => p.Name == _Name);
_UID_CUSTOMER = oPerson?.UID_CUSTOMER;
You can avoid nullable warning by removing this setting from csproj file您可以通过从 csproj 文件中删除此设置来避免可空警告
<Nullable>enable</Nullable>
And have these settings并有这些设置
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.