c#可空值类型会产生垃圾

本文关键字:空值 类型 | 更新日期: 2023-09-27 18:06:06

null值类型会产生垃圾吗?结构体不是在堆上创建的,而是在堆栈上创建的,因为它是值类型。但是,当该结构体变为可空时,它仍然是一个值类型并且仍然在堆栈上创建吗?

我问这个问题是因为我需要一个不产生垃圾的可空结构体

c#可空值类型会产生垃圾

结构体不是在堆上创建的,而是在堆栈上创建的,因为它是值类型。

这是一种常见的误解,完全是误导。结构体是在堆上创建的数组元素。在堆上创建一个结构体,它是类的字段。在堆上创建一个结构体,它是lambda的封闭外部变量。结构总是在堆上创建的。只有当已知结构体的变量生存期比它们所在方法的生存期短时,才会在堆栈上创建结构体。显然,如果它们的生存期长于方法!的堆栈帧,则不能在堆栈上创建它们。

而且,每个人都忘记登记。寄存器既不是堆也不是堆栈。如果优化器认为烧掉寄存器是值得的,那么没有什么可以阻止优化器生成一个结构体作为寄存器。

但是当该结构体为空时,它仍然是一个值类型吗?

是的。可空类型是一种值类型。(尽管它不满足泛型类型或方法的值类型约束,并且它具有特殊的装箱行为。)

仍然在堆栈上创建吗?

如果非空值类型已经在堆上创建,那么可空值类型也将在堆上创建。

我需要一个不产生垃圾的可空结构体。

如果非空结构体没有产生垃圾,那么可空结构体也不会。

看看MSDN上的Nullable (T),很明显,Nullable仍然是结构体,因此仍然在适当的堆栈上创建。

[SerializableAttribute]
public struct Nullable<T>
where T : struct, new()

不能只在栈上创建结构体

这篇文章解释了Nullable的工作原理。可空类型存储在内存的什么地方?

简明扼要的回答是,如果您不希望它们驻留在堆中,请创建它们:

局部变量或临时变量,并且局部变量不闭合匿名方法或lambda的外部变量和局部变量是不在迭代器块中。

把你的部分逻辑建立在这个事实上是相当冒险的,因为它可能会改变,而且没有保证。这也适用于原始值类型,所以哨兵值而不是使用Nullable<T>不会突然消除这个问题。

相关文章: