.NET中的null表示为什么?

7
我和同事聊天时谈到了null的话题。他告诉我在.NET背后,它只是一个非常小的数字。我一直认为对象只是没有指向堆上任何内存的指针,但我也不确定哪种说法正确。
所以我希望社区能够为我们澄清这个问题。 ;P
4个回答

18

它是0。

从ECMA-335规范中的ldnull片段:

可能认为ldnull是多余的:为什么不使用ldc.i4.0或ldc.i8.0呢?答案是,ldnull提供了一个大小不确定的null - 类似于不存在的ldc.i指令。但是,即使CIL包括ldc.i指令,保留ldnull指令对于验证算法仍然有益,因为它使类型跟踪更加容易。


我非常不同意null等于0这种说法... 0是一个值... null只是一个占位符,用于表示没有对象引用。把一个对象初始化为null,然后说“哦,它也等于值0”在我看来有点矛盾。 - lomaxx
1
@lomaxx - 确实是零;这是在CIL级别上实现的方式。你可以把它看作是一个特殊的内存地址,被解释为null。 - Greg Beech
3
@lomaxx:null 绝对是一个值。你可以像其他值一样使用它 - 传递它,将其分配给变量等。它的位表示全部为零。 - Jon Skeet

7

当可空类型实例被设置为null时,其底层值为零。

更具体地说,可空类型是一种结构,它将基础类型的值与布尔值的null指示器组合在一起。可空类型的实例有两个公共只读属性:HasValue,类型为bool,和可空类型的基础类型的Value

对于非空实例,HasValue为true,对于null实例,HasValue为false。

因此,当HasValue为true时,Value属性返回包含的值。当HasValue为false时,尝试访问Value属性会引发异常。但如果你能够访问它,你会发现它包含了零。


1
这里讨论的是 Nullable<T> - 而不是空引用。 - Jon Skeet
@Jon,你是在说我的“实例”使用不够准确吗? - HTTP 410
我想说的是,你整个回答都在谈论可空值类型,而问题只是谈论“null”,这可能涉及可空值类型,也可能只是引用的空值。实际上,它看起来更多是关于空引用而不是可空值类型,但很难确定。 - Jon Skeet

0

从我的经验来看,我相信 Nothing 不会起作用,DBNull.Value 也是如此。


...而我完全误解了它。我相信Null或'Nothing'在数值上等于零,并且存储为被赋给它的变量的数据类型。 - Sukasa
最好的做法可能是删除答案,否则你会收到负评 :) 对于诚实表示赞赏。 - leppie
现在你看到了“==”和“===”之间的区别,请尝试比较这些不同的 null 类型。 - TravisO

-2

来自MSDN

null关键字是一个字面量,表示一个空引用,即不引用任何对象

为了在旧版本的C#中更清晰地表达,值类型不能为null,即必须有一个值,如果您没有分配一个值,那么您将得到一个潜在的随机值,因此类似于:

int i;
i++;
console.writeline(i);

在早期版本的C#中,对象必须被初始化,否则它们将为null,这意味着它们没有引用任何对象。
现在,在C# 2.0+中具有可空值类型,您可以拥有可空int,这意味着如果您有以下代码:
int? i;
i++;
console.writeline(i);

由于i从未被初始化为除null以外的任何值,因此实际上会在i++处引发异常。如果null是0,则此代码将执行良好,因为它只会计算为0 + 1,但这是不正确的行为。

如果null始终为0,并且您有一个可空整数,并编写了以下代码:

int? i;
if (int == 0)
{
//do something
}

如果 null 和 0 相同,那么你可能会遇到一些意想不到的行为,因为编译器无法区分 int 是 null 还是显式设置为 0。

另一个例子可以更好地阐明这个问题:

public int? AddNumbers(int? x, int? y)
{
    if (x == null || y == null)
        return null;
    if (x == 0)
        return y;
    if (y == 0)
        return x;

    return x + y;
}

在这个例子中,很明显 null 和 0 是非常不同的,因为如果你将 0 传递给 x 或 y,而 null 等于 0,那么上面的代码就永远不会到达对 x == 0 或 y == 0 的检查,但是如果你运行代码并将 0 传递给 x 或 y,则检查确实会被执行。

我认为这并没有什么帮助。提升运算符的行为与 null 的基础值几乎没有关系。而且恰好,"null" Nullable<T> 的二进制值就是零。全是零。所以对于 int? 来说,它有 5 个零(一个用于布尔标志,4 个用于 int)。 - Marc Gravell
(注意,-1不是我发的;我更喜欢通过评论反馈,而不是盲目地投反对票)请返回翻译后的文本。 - Marc Gravell
lomaxx,可空类型是一种结构,它将基础类型的值与布尔空指示器组合在一起。如果该类型设置为 null 值,则其基础值为零,并且其空指示器设置为 true。 - HTTP 410
RoadWarrior... 这可能是“null如何表示”的最好解释。 - lomaxx
我猜有三种方式来问这个问题:null的基础值是什么?null的(面)值是什么?以及用于表示null的结构是什么?我试图回答第二个问题,而其他人则试图回答其他变体,所以可能就在那里引起了混淆。 - lomaxx
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接