gpt4 book ai didi

.net - 为什么/.Net 允许我否定一个 Nullable 是 null?

转载 作者:行者123 更新时间:2023-12-04 16:20:45 35 4
gpt4 key购买 nike

我发现自己盯着看起来与此类似的代码:

private double? _foo;

public double? Foo
{
get { return _foo; }
set { Baz(-value); }
}

public void Baz(double? value)
{
// Perform stuff with value, including null checks
}

在测试中,我有这个:
[Test]
public void Foo_test()
{
...
Foo = null;
...
}

我预计测试会失败(抛出),因为我认为您真的不能将一元减号应用于 null ,我相信这会发生在 Foo s二传手。然而,意想不到的事情发生了,测试做了 不是 失败。

我可能可以对为什么会发生这种情况做出明智的猜测,但我认为如果有人真正知道发生了什么事情可以启发我会更好。

(在有人指出显而易见的事情之前:是的,否定肯定应该被插入 Baz 的内部。)

编辑跟进

所以,我很感谢 Jon Skeet 和 JaredPar 的投入,他们都回答了我问题的 How 部分。经过一番谷歌搜索后,我发现 this blog post by Eric Lippert explaining the mathematical definition of 'lifted' ,这是完全有道理的。我还阅读了语言规范的相关部分,这些部分相当直接地解释了 c# 中的提升机制。

具体来说,我现在知道在提升过程的早期,会对操作数进行空检查,如果操作数为空,则空将是应用运算符的结果(在我的情况下为一元减号)。所以 -nullnull .

现在,到问题的“为什么”部分。如果我定义我自己的(一元) operator -class (其中我否定了一个包装的值),并在空引用上调用这个运算符,我将得到一个 NullReferenceException . 为什么“提升”的行为不同? 我实际上对这个设计决定背后的推理很感兴趣。我绝对是 不是 反对该决定。

最佳答案

Why is it, that 'lifting' behaves differently? I'm actually interested in the reasoning behind this design decision.



好吧,首先,您不应该总是得到空引用异常。静态调度运算符(operator)调用;它不需要做空检查。这是完全合法的:
class P
{
public static P operator -(P p)
{ return p; }

static void Main()
{
P p1 = null;
P p2 = -p1;
Console.WriteLine(p2 == null);
}
}

我真的认为您的问题的意思是“为什么可空值类型会自动从不可空操作提升为可空操作,但如果您想要可空语义,引用类型要求您在运算符中编写特定逻辑?”

有点乱。

问题是,引用类型一开始总是可以为空的,因此您始终可以自己编写该代码。由于后来添加了可空值类型,我们添加了一种机制,以便所有现有的不可空操作符突然可以与可空类型一起正常工作,这样您就不必自己编写所有无聊的代码。

但是还有一个更普遍的问题。更普遍的问题是我们将“null”混淆为两个不同的意思。在引用类型世界中,null 表示“我不引用任何对象”。在值类型世界中,null 意味着它在数据库中的含义:这个数量可能有一个值,但我们不知道它是什么。如果所有销售人员还没有报告结果,11 月份的销售数字是多少?该数量肯定有美元值(value),但我们不知道它是什么,所以我们将其标记为空。

提升算术旨在处理“数据库空”语义;空加十二是空的。你不知道的东西加上十二是你不知道的东西。不幸的是,由于我们直到第 2 版才向 C# 添加可为空的算术,因此已经有了将 null 视为“存在引用没有对象的对象引用”语义的所有工具。

如果我们从头开始设计整个事情,我的怀疑是 (1) 会有可为空的引用类型、不可为空的引用类型、可为空的值类型和不可为空的值类型,以及 (2) 会有更明确定义的区别在空引用和空值之间,或者它们的语义在算术方面会更加一致,并且(3)将所有不可为空的操作自动提升为可空操作。

请注意 VB/VBScript implement the more clear distinction by having two separate values: Null, which is database null, and Nothing, which is reference null .

关于.net - 为什么/.Net 允许我否定一个 Nullable<T> 是 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4369060/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com