变量的作用域是可以访问该变量的代码区域。
确定作用域遵循以下规则
- 只要类在某个作用域内, 其字段也在该作用域内。
- 局部变量存在于表示声明该变量的块语句或方法结束的右花括号之前的作用域内。
- 在 for while 或类似语句中声明的局部变量存在于该循环体内。
1. 局部变量的作用域冲突
很多程序在不同部分为不同的变量使用相同的变量名很常见。 只要变量的作用域是程序的不同部分,就不会有问题,
也不会产生多义性。但要注意,同名的局部变量不能在同一个作用域内声明两次。 例如不能使用下面的代码
class MyClass
{
int x = 10;
int x = 20;
}
上面这段代码 在同一个类作用域下 声明了 x 两次,产生了多义性, 这样是不行的。
class MyClassA
{
int x = 10;
}
class MyClassB
{
int x = 20;
}
上面这段代码是允许的。因为 第一个 x 是 MyClassA类下的成员, 而第二个确是 MyClassB 类下的成员。
他们的作用域不同,也就不会产生多义性。
我来来看看下面的代码示例
static int Main()
{
for(int = 0; i < 10; i++)
{
Console.WriteLine(i);
}
for(int i = 9; i >= 0; i--)
{
Console.WriteLine(i);
}
return 0;
}
这段代码很简单, 使用两个for循环打印0-9的数字, 再逆序打印0-9的数字, 重要的是在同一个方法中,代码中的变量 i 声明了两次。 可以这么做的原因是 i 在两个相互独立的循环内部声明, 所以每个变量 i 对于各自的循环来说是局部变量。
再看另外一个例子
static int Main()
{
int j = 20;
for(int i = 0; i < 10; i++)
{
int j = 30;
Console.WriteLine(j + i);
}
return 0;
}
如果运行这段代码,会产生一个错误。
什么原因呢? 我们先看一下函数 Main() 它的作用域下第一个 j 是相对于 Main函数的, 而第二个 j 是相对于 for循环的, 有人会问它们的作用域不一样啊,应该是可以执行的才对啊, 哈哈,这就要说到C# 运行机制啦,当程序运行时会读取到第一个 j
直到Main方法结束执行后, 变量 j 才超出作用域。 (也就是说在Main方法没有执行结束前,这个 j 一直都是合法的)
那第二个 j 呢, 他在for循环的作用域下又定义了一个 变量 j, 这个时候就会报错,因为在这个函数里 第一个 j 还没有被释放,所以for循环下的 j 是不合法的。因为编译器无法区分这两个变量,所以不允许声明第二个变量。
2.字段和局部变量的作用域冲突(这是个有意思的话题)
某些情况下,可以区分名称相同(尽管其完全限定名不同)、作用域相同的两个标示符。
这句话的意思是: 在一些特定情况下,C# 是可以区分名称相同两个名字的。
看下面这个例子
class MyClass
{
static int j = 20;
static void Main()
{
int j = 30;
Console.WriteLine(j);
return 0;
}
}
虽然在 MyClass 类作用域中 声明了两个 变量 j ,这段代码也会编译。 一个是在类级别上定义的j , 另一个是在 Main方法中定义的 j, 这里在Main方法中声明的新变量 j 隐藏了同名的类级别变量,所以在运行这段代码时 ,会显示数字 30;
所以到看到这里就得出一个结论: 局部变量可以隐藏同名的类级别下的变量
那问题来了,如果要引用类级别变量,该怎么办呢? 可以使用语法 object.fieldname, 在对象的外部引用类或结构的字段。
在上面的例子中,访问MyClass 类中的静态字段,不能使用类的实例,只能使用类本身的名称:
Console.WriteLine(MyClass.j);