c#可空值类型会产生垃圾
本文关键字:空值 类型 | 更新日期: 2023-09-27 18:06:06
null值类型会产生垃圾吗?结构体不是在堆上创建的,而是在堆栈上创建的,因为它是值类型。但是,当该结构体变为可空时,它仍然是一个值类型并且仍然在堆栈上创建吗?
我问这个问题是因为我需要一个不产生垃圾的可空结构体
结构体不是在堆上创建的,而是在堆栈上创建的,因为它是值类型。
这是一种常见的误解,完全是误导。结构体是在堆上创建的数组元素。在堆上创建一个结构体,它是类的字段。在堆上创建一个结构体,它是lambda的封闭外部变量。结构总是在堆上创建的。只有当已知结构体的变量生存期比它们所在方法的生存期短时,才会在堆栈上创建结构体。显然,如果它们的生存期长于方法!的堆栈帧,则不能在堆栈上创建它们。
而且,每个人都忘记登记。寄存器既不是堆也不是堆栈。如果优化器认为烧掉寄存器是值得的,那么没有什么可以阻止优化器生成一个结构体作为寄存器。
但是当该结构体为空时,它仍然是一个值类型吗?
是的。可空类型是一种值类型。(尽管它不满足泛型类型或方法的值类型约束,并且它具有特殊的装箱行为。)
仍然在堆栈上创建吗?
如果非空值类型已经在堆上创建,那么可空值类型也将在堆上创建。
我需要一个不产生垃圾的可空结构体。
如果非空结构体没有产生垃圾,那么可空结构体也不会。
看看MSDN上的Nullable (T),很明显,Nullable仍然是结构体,因此仍然在适当的堆栈上创建。
[SerializableAttribute]
public struct Nullable<T>
where T : struct, new()
不能只在栈上创建结构体
这篇文章解释了Nullable的工作原理。可空类型存储在内存的什么地方?
简明扼要的回答是,如果您不希望它们驻留在堆中,请创建它们:
局部变量或临时变量,并且局部变量不闭合匿名方法或lambda的外部变量和局部变量是不在迭代器块中。
把你的部分逻辑建立在这个事实上是相当冒险的,因为它可能会改变,而且没有保证。这也适用于原始值类型,所以哨兵值而不是使用Nullable<T>
不会突然消除这个问题。