内存中可存储的可空类型?

Ond*_*ták 32 .net c# nullable

这可能是关于可空类型的问题的后续问题.

哪些可以为空的值类型(int?...)存储在内存中?首先,我认为它很清楚,Nullable<T>结构和那些是值类型.然后我找到了Jon Skeet的文章" Memory in .NET ",其中说:

请注意,值类型变量永远不能具有null值 - 它没有任何意义,因为null是引用类型概念,意味着"此引用类型变量的值根本不是对任何对象的引用" .

阅读本声明后,我有点困惑.所以,让我说我有int? a = null;.由于int通常是值类型,是它在某种程度上内部存储结构Nullable<T>在堆栈(我用"正常",因为我不知道值类型会发生什么,当它变成可为空)?或者其他任何事情发生在这里 - 也许在堆中?

Eri*_*ert 74

首先,Nullable<int>它只是一个类似的简写:

struct Nullable<T> 
{
    bool hasValue;
    T value;
}
Run Code Online (Sandbox Code Playgroud)

加上所有构造函数,访问器等.这就是全部 - 可以为空的int是一个普通的int加上一个标志,表明int是否为null.剩下的就是将"null"视为有效值的编译器魔法; 使用可空类型的所有"null"都会使您将标志设置为false的结构之一.

所以现在我们已经把它排除在外,你的问题是"它们在记忆中的位置"?它们与内存中任何其他结构相同的位置:运行时和编译器相信在给定内存生命周期的最佳位置.

大多数结构都在堆上.任何告诉你"结构总是在堆栈上"的人实际上并不知道他们在谈论什么; 我们的文档没有说明,这不是真的.结构仅在临时内存池(即"堆栈")上,当它们是局部变量或临时变量时,并且局部变量不是封闭的匿名方法或lambda的外部变量,并且局部变量不在迭代器中块.在我们的实现中,所有其他结构都在堆上.

另请注意,CLI的实现不需要使用"堆栈"来创建临时池.例如,经典的JScript内存管理器将其临时池存储在堆上.(当然,JScript运行时引擎不是CLI的实现;我只是指出可以设计一个托管运行时引擎,它不会在"堆栈"上放置任何用户数据.)逻辑上它是一个堆栈数据结构,但该数据结构不存储在"堆栈"中,它只是在堆上分配的堆栈结构.

我不得不问:你为什么关心?CLR代表您管理内存.你为什么关心可空类型的去处?他们去了他们住的地方足够长的时间对你有用; 你不必担心.

  • @wcpro:当然应该.理解*为什么*被问到的问题是*绝对关键*给出满足提问者实际需求的答案!如果提问者是出于好奇,那就是一件事.**如果提问者将根据答案做出技术或业务决定,那完全是另一回事**.了解为什么有人想知道这一点非常重要,以便能够量身定制答案,为他们提供正确的信息,从而有效地做出决定. (15认同)
  • 一个非常容易+1的我.谢谢你的回答.我很在乎,因为我很好奇.我认为(可能是天真的)知道我的代码背后究竟发生了什么是有价值的信息.我不想最终编写一些神知道什么魔法的东西. (6认同)
  • 获得理解的问题不应该以"你为什么关心?"来回应. (5认同)
  • @Ondrej,如果您认为Nullable编译器支持是魔术,请尝试使用包含闭包的lambda表达式编写带有yield返回的IEnumerable方法.在ildasm中打开生成的程序,看看编译器为您做了什么. (2认同)

kem*_*002 7

请参阅Eric关于结构存储位置的注释.它比我发布的内容更彻底(也更正确).

它的工作方式是nullable有一个布尔值,表示该值是否已设置.从技术上讲,你是正确的nullable(int,bool)等实际上不是null.它有一个默认值.它只是现在可空类型有一个布尔值你可以检查并查看该值是否已设置或它只是它的默认值.的===被覆盖分配时设置适当的值null(和的值),以它

MSDN链接到Nullables

描述nullables如何工作的另一个链接:http:
//www.markzhou.com/blog/post/2010/01/27/Why-can-assign-e2809cnulle2809d-to-nullable-types.aspx

  • 结构并不总是存储在堆栈中.正确的语句是"结构类型的局部变量,它们不是匿名方法或lambda表达式的外部变量,不在迭代器块中,而是存储在桌面CLR的Microsoft实现中的堆栈上." 不要求存在称为"堆栈"的数据结构或者所有结构都存储在其上.在迭代器块或外部变量中作为类或本地字段的结构存储在堆上. (4认同)