我清楚地了解了参考和值类型在.NET中的工作方式。我知道引用类型的堆栈上的条目包含指向堆上的内存位置的指针。我似乎无法找到有关堆栈条目包含的其他内容的详细信息。所以,鉴于以下内容:
Customer customer;
customer = new Customer();
在第一行代码之后,将存在包含空指针的堆栈上的条目。该条目是否还包含识别名称“customer”?它是否包含类型信息?
我是否从根本上误解了某些事情?
答案 0 :(得分:11)
仅存储指向对象的指针,没有别的。不在堆栈上,它存储在处理器寄存器中。只有当方法很大并且寄存器更好地用于其他目的时,它才会存储在堆栈中。做出决定是the optimizer的工作。这通常不太可能发生,因为您可能正在使用Customer类的属性和方法,因此将指针保存在寄存器中是有效的。
否则,这是NullReferenceException可以告诉您什么引用无效的基本原因。将指针值关联回命名的"客户"变量只能由调试器完成。它需要PDB文件才能知道变量的名称,该名称在程序集的元数据中不存在。这就是为什么你不能使用Reflection来发现局部变量名和值的基本原因。
这也是为什么调试只有在项目的Debug版本中使用它时才能正常工作。这会禁用优化器并将指针值始终存储回堆栈插槽,从而允许调试器可靠地将其读回。这是一个很大的代价,你应该只部署项目的Release版本的基本原因。
答案 1 :(得分:2)
变量名customer
仅存在于源代码中(因为它对您的计算机不感兴趣)。在运行时,没有人知道如何在代码中调用变量。
Jon Skeet写了一篇关于what is stored on the heap and what goes to the stack的好文章。 第一段(变量中的内容是什么?)应该回答你的问题:
引用类型变量的值始终是引用或null。如果它是引用,则它必须是对与变量类型兼容的对象的引用。例如,声明为
Stream s
的变量将始终具有null或对Stream
类的实例的引用的值。 (请注意,Stream
的子类的实例,例如FileStream
,也是Stream
的实例。)与变量关联的内存槽只是引用的大小,无论它指的实际物体多么大。 (例如,在32位版本的.NET上,引用类型变量的插槽总是只有4个字节。)
答案 2 :(得分:2)
1-变量名不与参考一起存储在内存中。
2- A null
引用不存储对象的类型。
string str = null;
if(str is String)
{
Console.WriteLine("I'm a string");
}
else
{
Console.WriteLine("I'm not a string");
}
// This will print: "I'm not a string"
您实际上在告诉编译器,允许我使用str
的映射存储位置仅创建字符串引用。
变量代表存储位置。每个变量都有一个类型 确定哪些值可以存储在变量
中