C#未经初始化的variables是否危险?

我熟悉C#规范, 第5.3节说,使用前必须分配一个variables。

在C和非托pipeC ++中,这是有意义的,因为堆栈不被清除,并且指针的内存位置可能在任何地方(导致很难追踪错误)。

但我的印象是运行时没有真正的“未分配”值。 特别是未初始化的引用types将始终有一个空值,永远不会从先前调用方法或随机值遗留下来的值。

这是正确的,还是我错误地认为这些年来检查null是足够的? 你可以在C#中使用trully unintializedvariables,或者CLR是否处理这个问题,总是有一些值被设置。

我的印象是运行时没有真正的“未分配”值。 特别是未初始化的引用types将始终有一个空值,永远不会从先前调用方法或随机值遗留下来的值。 它是否正确?

我注意到,没有人真的回答你的问题。

你问的问题的答案是“sorta”。

正如其他人所指出的那样,一些variables(数组元素,字段等)被分类为被自动“初始赋值”为默认值。 (引用types为null,数字types为零,bools为false,用户定义的结构为自然recursion)。

有些variables未被分类为初始分配; 特别是局部variables不是最初分配的。 编译器必须在使用其值的所有点上将其归类为“明确赋值”。

那么你的问题实际上是“是一个局部variables,被归类为未明确赋值,实际上最初赋值方式与字段相同吗? 这个问题的答案是肯定的 ,在实践中,运行时最初分配所有的本地人。

这有几个很好的属性。 首先,您可以在debugging器中观察它们在第一次分配之前处于默认状态。 其次,垃圾收集器将不会被欺骗,只是因为堆栈中剩下的垃圾被当作一个托pipe引用而被废除。 等等。

运行时可以离开当地人的初始状态,因为无论垃圾发生在那里,只要能够安全地进行。 但作为一个实施细节,它从来没有select这样做。 它积极地为局部variables清零内存。

那么在使用之前必须明确分配的规则的原因并不是阻止你观察本地的垃圾未初始化状态。 这已经是不可观测的,因为CLR积极地清除本地的默认值,就像它为字段和数组元素一样。 在C#中这是非法的原因是因为使用未分配的本地很可能是一个错误。 我们只是把它变成非法的,然后编译器会阻止你有这样的错误。

据我所知,每种types都有一个指定的默认值。

根据本文档,类的字段被赋予默认值。

http://msdn.microsoft.com/en-us/library/aa645756(v=vs.71).aspx

本文档说以下内容始终具有自动分配的默认值。

  • 静态variables。
  • 类实例的实例variables。
  • 最初分配的结构variables的实例variables。
  • 数组元素。
  • 值参数。
  • 参考参数。
  • 在catch子句或foreach语句中声明的variables。

http://msdn.microsoft.com/en-us/library/aa691173(v=vs.71).aspx

有关这里的实际默认值的更多信息: http : //msdn.microsoft.com/en-us/library/83fhsxwc.aspx

特别是未初始化的引用types将始终为空值

我想你是混合局部variables和成员variables。 5.3节具体谈到局部variables。 与默认的成员variables不同,本地永远不会默认为空值或其他任何值:它们只是在第一次读取之前就被赋值。 5.3节解释了编译器用来确定一个局部variables是否被赋值的规则。

这取决于声明variables的位置。 在类中声明的variables会使用默认值自动初始化。

 object o; void Method() { if (o == null) { // this will execute } } 

在一个方法中声明的variables没有被初始化,但是当variables被首先使用时,编译器会检查它是否被初始化,这样代码就不会被编译。

 void Method() { object o; if (o == null) // compile error on this line { } } 

有三种方式可以给一个variables分配一个初始值:

  1. 默认情况下 – 例如,如果您声明一个类variables而不分配初始值,则会发生这种情况,所以初始值会得到default(type) ,其中type是您声明variables的任何types。

  2. 用一个初始化器 – 当你用一个初始值声明一个variables时,会发生这种情况,如int i = 12;

  3. 如果你有一个没有初始值的局部variables,就会发生这种情况(例如)。 编译器确保您没有可访问的代码path,它将在分配之前读取variables的值。

编译器在任何时候都不允许你读取一个未被初始化的variables的值,所以你不必担心如果你尝试了会发生什么。

所有的原始数据types都有默认值,所以不需要担心。

所有的引用types都被初始化为空值,所以如果你保持你的引用types未初始化,然后调用该引用types的某个方法或属性,你将得到一个运行时exception,需要适当的处理。

同样,所有可空types需要检查为空或默认值,如果他们没有被初始化如下:

  int? num = null; if (num.HasValue == true) { System.Console.WriteLine("num = " + num.Value); } else { System.Console.WriteLine("num = Null"); } //y is set to zero int y = num.GetValueOrDefault(); // num.Value throws an InvalidOperationException if num.HasValue is false try { y = num.Value; } catch (System.InvalidOperationException e) { System.Console.WriteLine(e.Message); } 

但是,如果您将所有variables初始化为编译器不会发出抱怨,那么您将不会得到任何complile错误,它只是您需要担心的运行时。