变量的作用域。
变量的作用域是指变量的作用范围。在C#代码行文中你几乎可以在任何地方定义变量,要注意的是,这些变量都有自己的作用范围,当执行超过其作用范围,该变量或对象就会被垃圾回收器回收。当相同名称的变量出现在同一段代码中时,我们可以根据其作用范围来区别谁是谁,比如下面代码,你考虑一下应该输出什么结果:
using System;
namespace Test
{
class Program
{
static void Main(string [] args)
{
for(int i=0;i< 1;i++)
{
string message="我是A";
Console.WriteLine(message);
}
for(int i=0;i<1;i++)
{
string message="我是B";
Console.WriteLine(message);
}
}
}
}
输出结果:
我是A
我是B
C#语言的作用域和Java等语言相同,也是以大括弧为界限。一个封闭的大括号就是一段相对独立的代码块,一段代码块就是一个作用域。如果变量是在该作用域内定义的,那么此变量的作用范围就是该代码块。上面的message变量都是在各自的for循环中定义的,它们的作用范围逃不出for循环的右大括弧。和Java及C++语言不同的是,C#中不能在同一个作用域中出现两个同名的变量,如:
using System;
namespace Test
{
class Program
{
static void Main(string [] args)
{
string message="我是X";
for(int i=0;i<1;i++)
{
string message="我是A";
Console.WriteLine(message);
}
}
}
}
编译这段代码,会出现错误:“不能在此范围内声明名为message的局部变量,因为这样会使message具有不同的含义,而它已在父级或当前范围中表示其他内容了”。上面的代码中值为“我是X”的message变量作用域为Main方法,很显然for循环也是它的作用范围,但此时你又在for循环内定义了同名的message变量,如此一来极易引起混乱,因此C#语法禁止了这种行为。另外,在后面我们还会接触到类的字段变量,当类的字段变量和方法中的局部变量名称相同时,变量的访问是根据“就近原则”进行的,如:
using System;
namespace Test
{
class Program
{
string message="我是X";
static void Main(string[] args)
{
for(int i=0;i<1;i++)
{
string message="我是A";
Console.WriteLine(message);
}
}
}
}
输出结果:
我是A
上面的代码中,我们在类Program里面定义了字段变量message,其值是“我是X”。在默认情况下这个message的作用域是整个类的任何地方,但此时在局部for语句中又有一个同名的message变量,那么此时message的访问就按“就近原则”来进行,即在for内访问的是值为“我是A”的message变量。
类型转换
虽然我们说C#中每一种数据类型的变量只能保存自己本类型的数据。但是为了增强变量之间的互操作性,C#和许多程序语言一样允许不同数据类型之间的数据转换。和Java及C++一样,C#中的类型转换也包括隐式转换和显式转换。隐式转换一般在低精度向高精度数据类型转换时自动发生,显式转换一般是用在差异非常大的数据类型之间。
当都是相同数据类型时,比如整型,隐式转换的方向是低容量向高容量自动转换,除此之外整型整体上都可以向浮点型转换。之所以有这个规律,很显然是因为如此的转换不会造成数据的丢失。
隐式转换示例如下:
using System;
namespace Test
{
class Program
{
static void Main(string [] args)
{
byte a=5;
short b=a;
int c=b;
long d=c;
float e=d;
double f1=e;
double f2=a;
}
}
}
隐式转换是自动进行的,而显示转换就需要相关的转换方法。C#中支持三种显示转换,一种是和Java及C++相同的方式,一种是通过Convert类,另外一种是通过类型自身的Parse方法。下面的例子中显示了这三种显示转换的用法:
using System;
namespace Test
{
class Program
{
static void Main(string [] args)
{
int a=int.Parse("3");
int b=(int)3.14;
int c=Convert.ToInt32(3.14);
float d=Convert.ToSingle("3.14");
string e=3.ToString();
Console.WriteLine("a={0},b={1},c={2},d={3},e={4}",a,b,c,d,e);
}
}
}
运行结果:
a=3,b=3,c=3,d=3.14,e=3.14
每一种基本数据类型都带有一个Parse方法,该方法用于将字符串数据转换成相应的数值类型。使用“(数据类型)”形式和使用“Convert.To…”方法都可以将源类型数据强制转换为目标类型数据,区别在于“(数据类型)”只支持兼容类型(比如都是数值类型)之间的强制转换,而“Convert.To…”方法支持的数据类型更广一些。比如上面的Convert.ToSingle可以将字符串类型转换为单精度浮点型,如果此时换成“(float)”就完成不了这个任务。很明显,强制类型转换会造成数据或者精度的丢失,在转换时要有心理准备。