由于C#10,Nullable在默认情况下将被禁用
我已经看到了很多关于Nullable的文章和视频,他们只是说我们不再担心Null引用异常。
他们还说有很多方法可以使用它:Disable
、Enable
、Warning
、Annotations
。。。。。布拉布拉。
介绍了?.
、??
、??=
、NotNullWhenTrue
、NotNullWhenFalse
。。。etc
但我没有看到任何人告诉我们:当它禁用时如何使用。
我们以前有很多场景需要使用null
。
1.属性:
// What is the default value when nullable disabled , and how way we should use it?
Public string Name { get; set; }
2.林克:
Person model = PersenList.Where(x => x.id == id).FirstOrDefault();
if (null != model)
{
// Do something
}
// How should we do when nullable diabled, what is the default value now, and how way we could check it a default value or not?
3.临时变量:
string ageDescription = null;
if (student.Age > 13)
{
ageDescription = "X";
}
if (student.Age > 15)
{
ageDescription = "XL";
}
if (student.Age > 18)
{
ageDescription = "XXL";
}
System.Diagnostics.Debug.WriteLine($"The Student size: {(ageDescription ?? "Not found")}");
// What should we do in this case, bring "Not found" at the began always?
或
string description = null;
if (student.Score < 70)
{
description = "C";
}
if (student.Score > 70)
{
description = "B";
}
if (student.Score > 80)
{
description = "A";
}
if (student.Score > 90)
{
description = "AA";
}
student.description = description;
JsonConvert.Serialize(student, {with Ignore Null Option for save more space});
// How do we save the json size and space, if we disable the nullable?
或
string value = null;
try {
value = DoSomething();
if (value == "Something1")
{
Go1();
}
if (value == "Something2")
{
Go2();
}
if (value == "Something3")
{
Go3();
}
} catch (Exception ex)
{
if (null == value)
{
GoNull();
}
else
{
GoOtherButException(ex)
}
}
// How should we handle this kind of problem?
4.实体框架
//The tables always has null field and how we deal with it when nullable disabled?
我知道我们可能会处理更多的情况。我觉得他们只是在虚张声势,有这么多可为null的功能太棒了,但没有给我们任何方向或好的方法来指出。
我希望有人已经使用了C#10,向我们指出在禁用Nullable后如何改变我们老式的代码样式,并给我们一些例子来向我们展示我们将来应该如何做。感谢
--------更新1-------
我添加了一些可变的例子。
--------更新2--------有些家伙说我们可以随心所欲。这是基于你的要求。如果你想使用它,只需简单地添加?
,比如:
string? name = null
但我更希望他们能告诉我:在每个地方都用String.Empty
代替null
。哈哈。。。。
但在这种情况下,每个地方我仍然需要检查if ( variable != String.Empty)
,但我们可以避免空引用异常,我也不确定String.Empty
会占用内存中的多少空间。
那么,为什么没有人告诉我们这样做呢:当他们告诉我们禁用nullable时,我们需要如何改变我们的代码样式
另一件事是,我真的不明白,在我们总是使用if (null != model)
之前,我们如何在使用FirstOrDefault()
时检查Linq的默认值。
也许我真的想知道:如果我们都禁用了可为null的,那么未来的世界会是什么样子。
我觉得需要澄清的第一件事是,启用可为null的引用类型不会影响代码是否可以构建。它对默认值没有影响。
可为null的引用类型旨在使您能够使用Express your design intent more clearly with nullable and non-nullable reference types
。这是很棒的教程的标题:可以为null的引用类型,我强烈建议任何试图深入研究这一功能的人阅读它
可为null的引用类型特性允许您显式声明:我从不希望这个(可为null类型)属性是未知的。因此,它应该总是有价值的。
若要声明您希望属性始终具有值,请将其定义为常规
public string Text { get; set; }
。
若要明确声明某个属性不一定具有值,将使用"?"进行定义类型之后
public string? Text { get; set; }
希望这个功能的意图现在或多或少已经清楚了。让我们深入探讨你的具体问题。
1.属性:
您的问题:
// What is the default value when nullable disabled , and how way we should use it?
public string Name { get; set; }
未初始化的字符串或类属性仍将为null。没有显式初始化的int仍然为0,没有显式初始化的boolean仍然默认为false。为了不重复关于如何使用它的相同文本,我只重复这一点。您应该将其用于Express your design intent more clearly with nullable and non-nullable reference types
。由您来标记解决方案中的所有类,以确定属性是否具有此特性。不,这样做不好玩。但你也不需要一次完成。您可以很容易地启用该功能(有大量警告),并稳步迈向一个或多或少包含所有类的解决方案。
2.林克:
Person model = PersonList.Where(x => x.id == id).FirstOrDefault();
// How should we do when nullable diabled, what is the default value now, and how way we could check it a default value or not?
如果你有一个Linq查询,你不确定你是否真的能找到你想要的东西(很多情况下都是这样),.FirstOrDefault()
仍然可以使用。但是Person model
应该通过将其更改为Person? model
来表示它可能为空。
3.临时变量:
你想让一个临时变量一开始为null,然后有条件地赋值吗?没问题,只要加上魔法"?">
或者!如果你确定要给它一个值,为什么不给它赋值呢?例如:
string description = string.Empty;
if (student.Score < 70)
description = "C";
// ... some more conditions ...
student.description = description;
4.实体框架
我认为,在数据访问层中,将非常清楚地标记哪些属性永远不会为空,哪些属性可能为空。只需查看数据库模型和查询/存储过程,以及在写入数据库之前所做的null检查。数据库中不能为null的所有内容都将在数据模型类中,并且可能包含的所有内容将标记为"?"在数据模型类中的类型之后。
如果启用了可为null的引用类型,世界会是什么样子
IDE将向您显示潜在意外null的警告。如果团队努力减少警告,这将导致属性明确说明它们是否为null。这是通过添加一个"属性类型之后。如果你确定某个东西不是空的,你可以添加一个"以抑制警告。
对于DTO类"是经常使用的东西。这是由于DTO类必须有一个空构造函数,并且其属性可以使用set;
或init;
属性进行设置。将显示警告。在这里,可以为文件禁用警告,或者可以用默认值(可以为null)初始化属性,并使用"&";。对于这两种方式,在使用它们之前,属性都应该是空保护的。
通过使用":
public List<string> Comments { get; set; } = null!;
一个常见的现象是,你很可能会看到空保护子句减少。如果您确信所调用的代码保证符合可为null的引用类型功能,则可以执行此操作。值得注意的是,这些属性可能仍然为null,因此您可以打开null引用异常,而不是参数null异常。尽管如此,在我看来,这是值得澄清和缩小规模的。但每个人都有自己的看法。堆栈溢出问题:启用了可为null的引用类型的何时为null检查参数
最终的结果是,您的代码将清楚地表达预期的变量,因此应该以可为null的方式处理,有时不存在。如果可能的话,这可能会导致更少的保护条款,并带来更少(样板)代码的好处
参考
我真的希望我能帮你一点忙。如果你对教程之外的知识有更多的渴望,这里有一些关于可为null的引用类型的真正好的文档:
- 教程:可为null的引用类型
- 使用可为null的引用类型
- 可为null的引用类型