为什么必须初始化C#局部变量?
我正在阅读MCTS自定步调训练包(70-536)第2版,在第1章中,我们有以下内容 如何声明值类型变量 要使用类型,必须首先声明 作为该类型实例的符号。 值类型具有隐式 构造函数,所以声明它们 自动实例化类型; 你不必包括新的 关键字,就像您处理类一样。这个 构造函数指定一个默认值 (通常为null或0)到新的 例如,但你应该始终 显式初始化变量 在声明中,如中所示 以下代码块: 但是,当我编译以下控制台应用程序时为什么必须初始化C#局部变量?,c#,variables,initialization,C#,Variables,Initialization,我正在阅读MCTS自定步调训练包(70-536)第2版,在第1章中,我们有以下内容 如何声明值类型变量 要使用类型,必须首先声明 作为该类型实例的符号。 值类型具有隐式 构造函数,所以声明它们 自动实例化类型; 你不必包括新的 关键字,就像您处理类一样。这个 构造函数指定一个默认值 (通常为null或0)到新的 例如,但你应该始终 显式初始化变量 在声明中,如中所示 以下代码块: 但是,当我编译以下控制台应用程序时 using System; using System.Collections.G
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ch1_70_536
{
class Program
{
static void Main(string[] args)
{
bool b;
Console.WriteLine("The value of b is " + b);
Console.ReadKey();
}
}
}
我得到了编译时错误
“未分配局部变量b的使用”
它甚至没有在报告中提到。我做错了什么还是这本书完全错了?您需要为
b
bool b = false;
除非你给它赋值,否则它是“未赋值的”你需要先给b赋值,否则它不会被初始化 尝试:
b现在为false。必须先分配局部变量,然后才能使用它们。但是,类字段将获得其默认值。 例如:
public bool MyMethod()
{
bool a;
Console.Write(a); // This is NOT OK.
bool b = false;
Console.Write(b); // This is OK.
}
class MyClass
{
private bool _a;
public void MyMethod()
{
Console.Write(_a); // This is OK.
}
}
方法(方法作用域)中的变量需要显式初始化。类级别的变量(或“字段”)将使用默认值自动初始化
class Test
{
bool b; // =false
int i; // =0
}
此语句确实应该详细说明,以表明尽管可以在不为局部变量赋值的情况下声明该局部变量,但在为其赋值初始值之前,不能使用该局部变量: 构造函数为新实例分配一个默认值(通常为null或0),但您应该始终在声明中显式初始化变量
在C#和VB.net中扮演拇指的角色,在调用任何变量之前,先初始化它。 像
关于VB,这本书基本上是正确的,但在本例中,它没有提到VB和C#之间的区别 在VB中,所有局部变量都会自动初始化:
Sub Test()
Dim x As Integer
MessageBox.Show(x.ToString()) 'shows "0"
End Sub
而在C#中,局部变量没有初始化,编译器不允许您使用它们,直到它们:
void Test() {
int x;
MessageBox.Show(x.ToString()); // gives a compiler error
}
此外,还不清楚这本书中的引文实际上是在谈论局部变量还是类成员变量。在VB和C#中创建类实例时,始终初始化类成员变量
这本书说“值类型有一个隐式构造函数”是错误的。这根本不是事实。值类型初始化为其默认值(如果已初始化),并且在这种情况下不会调用构造函数。在C#中,局部变量存储在堆栈中,编译器不会初始化它们以进行代码优化
所以这个引用,实际上甚至是值类型的指针,指向一个未定义的内存空间
因此,如果我们使用一个局部变量而没有将其设置为某个值,编译器就会知道我们将获得随机数据
下面是一个示例IL代码:
static void Test()
{
int a;
int b = 2;
}
.method private hidebysig static
void Test () cil managed
{
// Method begins at RVA 0x3044
// Code size 4 (0x4)
.maxstack 1
.locals init (
[0] int32 a,
[1] int32 b
)
// (no C# code)
IL_0000: nop
// int num = 2;
IL_0001: ldc.i4.2
IL_0002: stloc.1
// }
IL_0003: ret
} // end of method Program::Test
Int32
在堆栈中的位置0
为a
定义,但未指定默认值
class Test
{
bool b; // =false
int i; // =0
}
所以它的值是不确定的,并且可以从存储单元中得到任何值
对于位置
1
处的b
,稍后分配,一切正常。感谢您的澄清。因此,正如Nick指出的,局部变量是初始化的,但是在我们显式地为它分配一个新值之前不能使用。正确吗?不,它们不是自动初始化的。这就是为什么您需要自己初始化它们。只有类字段会为您自动初始化@Nick谈到了类字段。我想你指的是声明的而不是初始化的。如果不给变量赋值,就不能初始化变量,初始化变量时就是这样做的。
void Test() {
int x;
MessageBox.Show(x.ToString()); // gives a compiler error
}
static void Test()
{
int a;
int b = 2;
}
.method private hidebysig static
void Test () cil managed
{
// Method begins at RVA 0x3044
// Code size 4 (0x4)
.maxstack 1
.locals init (
[0] int32 a,
[1] int32 b
)
// (no C# code)
IL_0000: nop
// int num = 2;
IL_0001: ldc.i4.2
IL_0002: stloc.1
// }
IL_0003: ret
} // end of method Program::Test