当我们只声明一个类的对象而不像下面那样实例化它时,它会将其视为null还是空或者其他?
示例1:Directory objDEntry;
示例2:Directory objDEntry = null;
Example1和Example2之间是否有区别或它们相同?
答案 0 :(得分:2)
取决于;如果您声明字段,例如
public class MyClass {
// objDEntr will be initialized by null
Directory objDEntr;
// the initialization is redundant here
Directory objDEntry2 = null;
...
没有区别,因为字段是按其默认值初始化的,而null
是引用类型的默认值。但是,默认情况下不会初始化局部变量;所以
public static void MyMethod() {
// objDEntry contains trash, must be initialized further
Directory objDEntry;
// objDEntry2 is null
Directory objDEntry2 = null;
...
“示例1”中的 objDEntry
包含垃圾,而“示例2”objDEntry
已正确初始化并包含null
。
答案 1 :(得分:1)
当声明引用类型变量时,该变量基本上是指向表示特定对象的内存集合的指针。例如,在您的情况下,当您声明Dictionary
变量时:
Dictionary objDict;
这将创建指向内存中Dictionary
对象的指针。但是,当它首次声明时,变量实际上并没有指向任何东西。此时尝试在任何计算中使用变量将产生NullReferenceException
。
另一方面,当您创建对象时,它会为该对象分配内存。 (为了这个解释,准确分配内存的地方是无关紧要的。)所以当你创建一个Dictionary
对象时:
new Dictionary();
这将分配表示Dictionary
对象所需的内存。
当您将这两个操作绑定在一起时,这就是您在分配引用类型变量时所执行的操作:
Dictionary objDict = new Dictionary();
变量objDict
现在指向为对象分配的内存。
现在,当您将null
分配给引用变量时,您基本上将其重置为默认状态 - 指针指向任何位置的状态。在这个意义上,行:
Dictionary objDict;
和
Dictionary objDict = null;
就CLR而言,将是相同的。但是,C#编译器带有自己的一组限制,其中涉及变量声明。它将通过编译错误强制要求在保证显式实例化之前不能使用引用变量。例如,以下内容将编译,但会在运行时抛出错误:
Dictionary objDict = null;
string s = objDict.ToString();
但是,此代码在编译时将失败,并显示错误消息“使用未分配的局部变量'objDict'”:
Dictionary objDict;
string s = objDict.ToString();
正如德米特里在答案中所说,这条规则只适用于局部变量。类级别和以上变量不会产生这样的错误,因此以下代码可以正常使用:
Dictionary objDict;
public void DictToString()
{
string s = objDict.ToString();
}
为了解释Hameed所说的内容,引用变量是指向内存中对象的指针,但是当你获取一个赋值变量并将其设置为null
时,该前一个对象仍在内存中 - 它具有刚刚成了孤儿。当CLR执行垃圾收集时,它会精确检查这些孤立的对象并释放它们的内存。
它不会(通常)收集仍然具有指向它们的活动指针的对象,但是,这就是为什么对于某些对象来说,通过将指向它们的变量设置为{{1}来处置它们是一种好习惯。这样它们就会在下次垃圾收集时被正确释放。