C#未初始化的变量是危险的吗?

jmo*_*eno 36 c# clr

我熟悉C#规范,第5.3节,它说在使用之前必须分配一个变量.

在C和非托管C++中,这是有道理的,因为堆栈没有被清除,并且用于指针的内存位置可能在任何地方(导致难以追踪错误).

但我的印象是运行时不允许真正的"未分配"值.特别是未初始化的引用类型将始终具有空值,而不是先前调用方法或随机值所遗留的值.

这是正确的,还是我错误地假设这些年来检查null是否足够?你可以在C#中使用非真实的变量,或者CLR是否会处理这个变量并且总是设置了一些值.

Eri*_*ert 63

我的印象是运行时不允许真正的"未分配"值.特别是未初始化的引用类型将始终具有空值,而不是先前调用方法或随机值所遗留的值.它是否正确?

我注意到目前还没有人回答你的问题.

你实际问的问题的答案是"sorta".

正如其他人所指出的,一些变量(数组元素,字段等)被归类为自动"初始分配"为其默认值.(对于引用类型,它为null,对于数字类型为零,对于bools为false,对于用户定义的结构为自然递归).

有些变量未归类为初始分配; 特别是局部变量最初没有分配.它们必须在编译器中被分类为使用其值的所有点处的"明确分配" .

那么你的问题实际上是"是一个局部变量,它被分类为没有明确分配,实际上最初的分配方式与字段相同?" 这个问题的答案是肯定的,在实践中,运行时最初会分配所有本地人.

这有几个不错的属性.首先,您可以在调试器中观察它们在第一次分配之前处于默认状态.其次,垃圾收集器不可能被欺骗去取消引用坏指针,因为堆栈上剩下的垃圾现在被视为托管引用.等等.

允许运行时离开本地的初始状态,如果它可以安全地发生在那里的任何垃圾.但作为一个实现细节,它永远不会选择这样做.它积极地将内存归零为局部变量.

因此,在使用本地人之前必须明确分配规则的原因并不是要阻止您观察本地的垃圾未初始化状态.这已经不可观察了,因为CLR会主动将本地清除为默认值,与字段和数组元素相同. 这在C#中是非法的原因是因为使用未分配的本地很可能是一个bug.我们只是将其设为非法,然后编译器阻止您有这样的错误.


Joe*_*Joe 9

据我所知,每种类型都有一个指定的默认值.

根据此文档,类的字段将分配默认值.

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

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

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

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

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


Tim*_*m B 5

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

object o;
void Method()
{
    if (o == null)
    {
        // This will execute
    }
}
Run Code Online (Sandbox Code Playgroud)

在方法中声明的变量不会被初始化,但是当第一次使用该变量时,编译器会检查以确保它已被初始化,因此代码将无法编译。

void Method()
{
    object o;
    if (o == null) // Compile error on this line
    {
    }
}
Run Code Online (Sandbox Code Playgroud)