1.3 C#语言
ASP.NET是一个Web编程的平台,其可选的编程语言很多,C#是最值得推荐的,因为C#语言是为.NET平台量身定做的。本节中所用的例子,用户可以在VS2008的“Windows控制台”类型的项目中进行练习。如果对C#已有一定了解的读者可以跳过此节。
1.3.1 C#速览
C#语言的语法风格与C/C++十分相似,有C/C++相关编程经验的读者能够很容易上手。下面是一段C#程序:
class Program { static void Main(string[] args) { int a = 5; int b = 2; if (a > b) { int c = a; a = b; b = c; } Console.Write("按先小后大顺序显示:{0},{1}", a, b); } }
这段程序完成的功能是将a和b两个数按从小到大的顺序进行排序,通过这个程序可以看出C#的语法特点。
(1)语法风格与C/C++极其相似,如定义类的关键字class,定义静态函数的关键字static,{…}花括号的程序体,if关键字等等。对C/C++有点基础的程序员基本上一眼就能读明白简单C#程序的意义。
(2)C#是一种完全面向对象的语言。这与C或C++都不一样,C是完全结构化的语言,C++是既兼容结构化又支持面向对象的语言。这一点从以上程序就可以看出,同样是Main方法,在C和C++中是不需要定义在一个类中的,而C#不同,所有的方法(即函数)都必须定义在类中,因此上段程序的最外面是一个类:class Program,类名为“Program”,也可以取其他的名字。
1.3.2 C#语言的数据类型及运算符
C#语言的数据类型分为两大类:值类型和引用类型。值类型的变量直接存储所包含的值;引用类型不是直接存储值,而是指向存储值的地址,在C/C++中称之为指针类型,但C#是托管代码,不允许使用指针,所以通过引用类型进行封装。
以下是值类型。
1. 整数类型
要注意与C/C++进行区别的是各种类型的长度,short、int、long型都比C/C++多出一倍的长度,其存储值的范围也多出一个平方的数量级。
2. 浮点类型
C#的浮点型也比相应的C/C++类型存储长度多出一倍,而且多加了一种称为decimal的类型,以便记录更加精确的小数。
3. 字符类型
C#的字符型比C/C++中的char型要多一倍的长度,储存的编码格式不再是ASCII码,而是Unicode。在.NET中所有的字符编码全部采用Unicode编码格式,这个编码格式的特点是每一个字符都是以两个字节(16 bits)来储存的,因此无论英文字母还是汉字,在计算长度时,一个汉字不再算成是“两个英文字符”,而也算是“1个字符”。同样地,C#也有一些转义字符,如:char c='\x0032'、char c='\\'、char c='\r\t'等。
4. 布尔类型
布尔类型与C/C++完全不一样,C#中的布尔类型常量是True、False这两个关键字,因此不存在存储长度这样的概念。C#中也不能像C/C++中将0等同于“假”,非0等同于“真”了,只能是True或False,不能与整型等同。
5. 结构类型
与C/C++一样,也是通过关键字struct来定义结构类型,如:
struct Student { public string Name; public int Age; } Student s; s.Name = “Mike”; s.Age = 21;
结构类型与类的定义是十分相似的。struct定义体中,除了字段还可以包括构造函数、常量、方法、属性等;但与类的本质区别在于结构体是按值传递的,而类是按引用传递的。
6. 枚举类型
枚举类型是C/C++所没有的,但Pascal和Delphi语言中有。这很好理解,因为C#之父Anders Hejlsberg就是Turbo Pascal和Delphi之父。枚举类型可以与int类型进行强制转换,如:
enum MyColor { Red,Blue,Green } 也可以写成: enum MyColor { Red=3, Blue=7, Green=12 } MyColor color = MyColor.Blue;
color可以强制转换为int型,如:(int)color。如果枚举项未被明确定义值,(int)color的值为其顺序号(第一项为0,第二项为1……);如果枚举项被明确定义值,(int)color则为该项的定义值,上述中其值为7。
以下数据类型为引用类型。
(1)类(class)。
类是面向对象编程的基本单位,C#的类中可以包含以下内容。
字段:
private int myAge=10;
字段相当于C/C++中的变量的概念,字段名约定以小写字母开头。
属性:
public int MyAge { get{return this.age;} set{this.age=value;} }
属性与字段最大的区别在于属性有get或set两种方法。在读取属性时,系统会自动执行get方法中的程序;在赋值时,系统会自动执行set方法中的程序。set方法中的value意义为用户对属性所赋的值。get、set、value都是C#中的关键字。属性名约定首字母以大写开头。
方法:
public int GetMyAge() { return this.age; }
方法其实就是C/C++中的函数,类中的函数一般习惯称之为方法。构造函数和析构函数是两个特殊函数,构造函数是在new一个类的对象时执行的方法,析构函数是在类的对象释放出内存时执行的方法。如:
public class Student { public Student() //构造函数没有返回值类型,可以带参数 {…} ~public Student() //析构函数也没有返回值类型,不带参数,也不能显式地被调用 {…} }
类中还可以包含其他类的定义,也可以枚举定义。
在C#语言中,或者说对于.NET Framework,所有的类都是从同一个基类中直接或间接继承下来的,这个类叫“Object”。所以任何类型的变量都可以强制转换为Object类型。如:
int a = 2; Object obj1 = a; Object obj2 = 'A';
(2)代表(delegate)。
代表就是C/C++中的指向函数的指针,即指针函数。如:
delegate int MyDelegate(int a,int b); //声明一个代表,此代表是一个返回值为int, 带两个整型参数的方法 public class MyClass { public int AddNum(int a,int b) { return a + b; } public static int MultiNum(int a, int b) //静态方法 { return a * b; } } class Program { static void Main(string[] args) { MyClass my = new MyClass(); MyDelegate myFunc1 = new MyDelegate(my.AddNum); int sum = myFunc1(2, 3); MyDelegate myFunc2 = new MyDelegate(MyClass.MultiNum); //静态方法的引用 int multi = myFunc2(2, 3); Console.Write("和={0},积={1}", sum, multi); Console.ReadKey(); //按任意键退出 } }
程序运行的结果为:
和=5,积=6
(3)数组。
数组在C/C++中也有,C#的数组与C/C++一样,也是按地址引用的,其本质也是指针。如:
int[] nums = new int[5]; nums[0] = 1; MyClass mys = new MyClass[10]; mys[3] = new MyClass(); char[] chs = new[] {'a','b','c'}; 以下是多维数组的定义方法。 int[,] nums = new int[3,4]; //二维数组 int[,,] n = new int[10,20,30]; //三维数组 int[,] m = { { 1, 2, 3 }, { 4, 5, 6 } }; (4)泛类型。 类似于C++中的模板,举例如下: public class Generic<Template> { public Template Field; } 以上是定义,下面是使用: Generic<string> g = new Generic<string>(); g.Field = "A string";
泛类型从使用上来说,有点像Word的查找替换功能,将泛类型对象化时,将< Template >中的“Template”在类的定义程序体中用指定的类型(本例中是string类型)查找替换掉,当然这种解释只是为了好理解泛类型的用法,其实质要比查找替换复杂得多。
下面来看看C#的运算符。
C#的运算符与C/C++类似,分为3类:单目运算符(如:“++”)、双目运算符(如:“+”、“-”、“*”)、三元运算符(只有一个:“? :”)
下面为按优先级顺序列出C#的运算符。
C#的赋值“=”运算符与比较等“==”运算符是不能够混用的,if语句(或其他条件判断语句)中只能用比较等“==”,因为C#中布尔型和整数型是完全分开的。
1.3.3 流程控制
1. 选择控制
if…else…语句,如: if(a>b) { c=a-b; } else { c=b-a } switch…case…语句,如: switch(color) { case MyColor.Red: Response.Write(“红色”); break; case MyColor.Blue: Response.Write(“蓝色”); break; case MyColor.Green: Response.Write(“绿色”); break; default: Response.Write(“无色”); break; }
switch(x)中的变量x可以是以下类型:sbyte,byte,short,ushort,int,uint,long,ulong,char,string或枚举类型,上述中就是一个枚举类型。
2. 循环控制
while语句,如:
int s = 1,i = 5; string result = string.Format("{0}的阶乘=", i); while (i > 0) { s *= i--; } result += s.ToString(); Console.Write(result);
do…while语句,如:
int s=1 , i=1; do { s*=i++; } while(i<=5); Console.Write("5的阶乘={0}", s);
do…while和while语句的区别就在于do…while语句至少会执行一次。
for语句,如:
for(int i=0;i<10;i++) Console.Write(i.ToString());
for语句与C/C++中的for语句几乎完全一致。
foreach语句,如:
char[] chs = new[] {'a','b','c'}; string result = string.Empty; foreach (char c in chs) { result += c;//注意这个c是哪里定义的 } Console.Write(result);
对于C/C++语法来说,这是C#中新引入的,借鉴了VB的优秀经验。它表示收集一个集合中的各元素,并针对各个元素来执行程序体中的语句。
foreach不仅可以列举出数组中的元素,只要是该类型具有必需的GetEnumerator()、MoveNext()、Reset()和Current()方法,就可与foreach一起使用。
在以上的循环语句中,均可以使用break关键字提前跳出循环,使用continue关键字结束本次循环。
与流程控制有关的语句还有捕捉错误的try…catch语句,其用法与C++相似,这里不再单独讲解,在后面的章节遇到相关程序段时,将结合实例进行讲解。
null表示还没有定义。对于引用类型的变量来说,null表示指针没有指向任何地址,C#中引用类型变量的初始值为null。对于值类型而言,null也有重要的意义。例如,将bool型变量设置为null,表示该布尔型既不是True,也不是False。
C#3.0中的新语法将在后面讲解Linq技术时集中进行讲解。