240 likes | 389 Views
第 2 章 数据类型与流程控制. 2.2.2 引用类型 C# 语言中的另一大数据类型是引用类型。 “ 引用 ” 指的是该类型的变量不是直接存储所包含的实际数据,而是存储实际数据的地址。 C# 语言中的引用类型有 4 种,类、委托、接口和数组。 1 、类 类是面向对象编程的基本单位,是一种包含数据成员、函数成员和嵌套类型的数据结构。类的数据成员有常量、域和事件。函数成员包括方法、属性、索引指示器、运算器、构造函数和析构函数。类和结构同样都包含了自己的成员,但它们之间最主要的区别在于:类是引用类型,而结构是值类型。
E N D
第2章 数据类型与流程控制 2.2.2 引用类型 C#语言中的另一大数据类型是引用类型。“引用”指的是该类型的变量不是直接存储所包含的实际数据,而是存储实际数据的地址。C#语言中的引用类型有4种,类、委托、接口和数组。 1、类 类是面向对象编程的基本单位,是一种包含数据成员、函数成员和嵌套类型的数据结构。类的数据成员有常量、域和事件。函数成员包括方法、属性、索引指示器、运算器、构造函数和析构函数。类和结构同样都包含了自己的成员,但它们之间最主要的区别在于:类是引用类型,而结构是值类型。 类支持继承机制,通过继承,派生类可以扩展基类的数据成员和方法,进而达到代码重用和设计重用的目的。
第2章 数据类型与流程控制 2.2.2 引用类型 2、委托 委托是指引用方法的类型,它实际上相当于C++语言中的函数指针原型,但与指针不同的是,委托在C#语言中是安全的,它允许实例化和调用类的静态方法,也可以调用类的指定实例的方法。在声明委托类型时,只需要指定委托指向的原型的类型,它不能有返回值,也不能带有输出类型的参数。
第2章 数据类型与流程控制 2.2.2 引用类型 3、接口 接口是一组包含了方法的数据结构。通过这组数据结构,可以在代码中调用组件对象的功能。接口可以从父接口中继承,但实际含义是说明继承,而不是实现性继承。它的实现需要通过类或结构来完成。接口的成员可以是方法、属性、索引指示器和事件,但不能是常量、域、操作符和构造函数,而且不能包含任何静态成员。
第2章 数据类型与流程控制 2.2.2 引用类型 4、数组 数组和结构不同,结构一般用于存储多种类型的数据,而数组则用于存储同一种类型的数据。数组是一种引用类型,而不是值类型。数组是按照数组名、数据元素的类型和维数来描述的。C#语言中可以有一维数组和多维数组,多维数组中又可以分为矩形数组和交错数组。 (1)数组的声明 C#语言可以在声明时不对数组进行初始化,需要使用数组时再在程序中动态地指定其大小,如表2-6所示。
表2-6 数组的声明语法 4、数组 (1)数组的声明
例如: int[ ] Integers; //声明一个int型的数组Integers; Integers=new int[30]; //指定数组Integers共有30个元素; 在实际使用中,如果预先知道数组的大小,也可以将这两个语句合而为一,例如: int[] Integers=new int[30]; //创建一个包含30个int型元素的数组Integers; 如果在数组声明时已经知道数组元素的初始值,也可以在声明语句中直接为其赋值,例如: string[ ] mystring={”first”,”second”,”third”}; 它等价于: string[ ] mystring=new string[] {”first”,”second”,”third”}; 4、数组 (1)数组的声明
访问共有32个元素数组中的单个元素时,其下标是从0 开始索引的,例如: Integers[0]=23; // 为Integers数组中的第一个元素赋值23; Integers[31]=67; // 为Integers数组中的最后一个元素赋值67; 在数组操作中经常使用的一个重要属性是数组的长度。要确定一维数组的长度,可以使用Length属性,例如: int ArrayLength=Integers.Length; 如果是多维数组,则可以使用GetLength方法确定其某一特定维的长度,例如: int ArrayLength=Integers.GetLength(0); //获取Integers数组第一维的长度 C#语言中还提供了Sort和Reverse这样的静态方法,可以将数组按照升序或降序排列。 4、数组 (2)数组的使用
[例2-4]使用Sort和Reverse方法对数组排序。 using System; namespace ArrayExample1 { class Program { static void Main() { //定义一维数组Artists,并赋初始值 string[] Artists={"Leonardo","Monet","Van Gogh","Klee"}; //将数组Artists做升序排列,并输出其结果; Array.Sort(Artists); for(int i=0;i<Artists.Length;i++) { Console.WriteLine(Artists[i]); } //将数组Artists做降序排列,并输出其结果; Array.Reverse(Artists); for(int i=0;i<Artists.Length;i++) { Console.WriteLine(Artists[i]); } Console.ReadLine(); } } } 输出结果: Klee Leonardo Monet Van Gogh Van Gogh Monet Leonardo Klee
(3)多维数组 C#语言支持两种类型的多维数组,一种是矩形数组,另一种是交错数组。在多维数组中,最常用的是二维数组。对于二维矩形数组,数组中的每一行都有相同的列数;而二维交错数组的每一行可以有不同的列数。显然,交错数组比矩形数组更灵活,但它的创建和初始化也更复杂一些。 [例2-5]数组的常用形式和使用的方法。 using System; namespace ArrayExample2 { class Program { static void Main() { //一维数组 string[] strArray1={"C","C++","C#"}; string[] strArray2=new string[3]; //指定元素个数并赋初值 int[] intArr1=new int[4]{0,1,2,3}; //直接赋初值 int[] intArr2={5,6,7}; int nVar=5; int[] arrToo=new int[nVar];
//二维矩形数组 int[,] myArr1={{0,1},{2,3},{4,5}}; int[,] myArr2=new int[2,3] {{11,12,13},{21,22,23}}; //二维交错数组 string[][] stra=new string[3][]; stra[0]=new string[2]{"a11","a12"}; stra[1]=new string[3]{"b11","b12","b13"}; stra[2]=new string[5]{"a","e","u","i","o"}; //输出一维数组 for(int i=0;i<strArray1.Length;i++) { Console.Write("strArray1[{0}]={1}",i,strArray1[i]); } Console.WriteLine(); //输出二维矩形数组的元素 for(int i=0;i<3;i++) { for(int j=0;j<2;j++) Console.Write("myArr1[{0},{1}]={2}",i,j,myArr1[i,j]); Console.WriteLine(); }
//输出二维交错型数组的元素 for(int i=0;i<stra.Length;i++) { for(int j=0;j<stra[i].Length;j++) Console.Write(" stra[{0}][{1}]={2}",i,j,stra[i][j]); Console.WriteLine(); } Console.ReadLine(); } } } 输出结果: strArray1[0]=C strArray1[1]=C++ strArray1[2]=C# myArr1[0,0]=0 myArr1[0,1]=1 myArr1[1,0]=2 myArr1[1,1]=3 myArr1[2,0]=4 myArr1[2,1]=5 stra[0][0]=a11 stra[0][1]=a12 stra[1][0]=b11 stra[1][1]=b12 stra[1][2]=b13 stra[2][0]=a stra[2][1]=e stra[2][2]=i stra[2][3]=o stra[2][4]=u
第2章 数据类型与流程控制 2.2.3 值类型之间的数据交换 值类型之间的数据交换可以相互转换。如果仅仅是数据表示范围不同的数据类型之间的转换,例如,int型和long型的数据转换,比较常用的两种转换方式是:隐式转换与显示转换。如果是不同值类型之间的转换,则可以使用Convert类。 1、隐式转换 隐式转换就是系统默认的、不需要加以声明就可以进行的转换,如从int类型转换到long类型: int k=1; long i=2; i=k; //隐式转换 在进行隐式的类型转换时,其实就是从低精度、小范围的数据类型转换为高精度、大范围的数据类型。这种转换一般没有问题,这是因为大范围类型的变量具有足够的空间存放小范围类型的数据。表2-7中列出了C#语言支持的隐式转换的类型。
2、显式转换 显式转换,又称强制转换。显式转换需要用户明确指定转换的类型。例如: long k=5000; int i=(int)k; 所有的隐式转换也都可以采用显式转换的形式来表示。例如: int i=10; long j=(long)i; 在将大范围类型的数据转换为小范围类型的数据时,必须特别谨慎,因为此时有丢失数据的危险。例如: long r=3000000000; int i=(int)r; 执行上述语句之后,得到的i值为-1294967296,显然是不正确的。这是因为上述语句中,long型变量r的值比int型的最大值+2147483647还要大,而语句中又使用了强制的类型转换,系统对这种转换不会报错,会强制执行,从而导致数据溢出,发生错误。
2、显式转换 如果的确需要使用显式的类型转换,但又不知是否会发生溢出而导致数据错误,可以使用checked运算符来检查数据类型是否安全。如上例,可以写为: long r=3000000000; int i=checked(int)r; 在这种情况下,如果出现溢出,系统就会在运行时抛出一个溢出异常,不会使程序继续运行。 另外,C#语言中还提供了一个Convert类,也可以用于各种值类型之间的转换,有关Convert类的使用方法将在第3章介绍。
[例2-6] 显式转换和隐式转换。 using System; namespace TypeConvertExample { class Program { public static void Main() { int i=10; long j=20; double k=30D; //隐式转换 j=i; k=j; Console.WriteLine("{0},{1},{2}",i,j,k); k=36.0D; //显式转换 j=(long)k; i=(int)j; Console.WriteLine("{0},{1},{2}",i,j,k); Console.ReadLine(); } } } 输出结果为: 10,10,10 36,36,36
2.2.4 装箱和拆箱 装箱和拆箱功能使得C#语言中所有的值类型都可以与object类型实现双向转换。 1、Object类 Object类是所有其他类型的基类,C#语言中的所有类型都直接或间接地从Object类中继承。因此,可以使用Object类引用绑定任何特定子类型的对象。 值类型与Object类型之间的转换有什么意义呢?举个例子,在程序中可以直接这样写: string s=(10).ToString(); 数字10只是一个堆栈上的4字节的值,怎么能实现调用它上面的方法呢?实际上,C#语言是通过装箱和拆箱操作来实现的,即先把10转换为引用类型,然后再调用引用类型的方法来实现指定的功能。
2.2.4 装箱和拆箱 2、装箱 装箱是将值类型隐式地转换为Object类型。装箱一个数值会为其分配一个对象实例,并把该数值复制到新对象中。例如: int i=123; object o=i; //装箱 这条装箱语句执行的结果是在堆栈(Stack)中创建了一个对象o,该对象引用了堆(Heap)上int类型的数值,而该数值是赋给变量i的数值的备份。 3、拆箱 拆箱是显式地把Object类型转换成数值类型。拆箱操作包括以下两个步骤: (1)检查对象实例,确认它是给定值类型的包装数值; (2)把实例中的值复制到值类型的变量中; 下面的语句演示了装箱和拆箱操作。 int i=123; //值类型 object box=i; //装箱操作 int j=(int)box; //拆箱操作 可以看出来,拆箱正好是装箱的逆过程,但必须注意的是,装箱和拆箱必须遵循类型兼容的原则。
2.2.5 运算符与优先级 C#语言有三大类运算符。 一元运算符:带有一个运算对象,例如,i++。 二元运算符:带有两个运算对象,例如,x+y。 三元运算符:带有3个运算对象,例如, <条件>?<条件成立时结果表达式>:<条件不成立时结果表达式>。 5>3?58:98 //结果为58 表2-8列出了常用运算符及其相关说明。
当一个操作数出现在两个有相同优先级的操作符之间时,操作符按照出现的顺序由左至右执行。如果无法确定操作符的有效顺序,则可以在编程时采用括号“()”进行指定,从而保证运算的顺序正确无误,也使得程序一目了然。当一个操作数出现在两个有相同优先级的操作符之间时,操作符按照出现的顺序由左至右执行。如果无法确定操作符的有效顺序,则可以在编程时采用括号“()”进行指定,从而保证运算的顺序正确无误,也使得程序一目了然。
//表达式举例 using System; class OperatorExample { public static void Main() { int i=1,j=2,a,b; Console.WriteLine("{0},{1},{2}",i++,i,++i); Console.WriteLine("{0},{1},{2}",--j,j,j--); Console.WriteLine(65>12?65:98); a=b=2; a+=5; b*=5; Console.WriteLine("{0},{1},{2}",a,b,a+b); Console.WriteLine("{0}",5>10&&100>200||38>16); Console.ReadLine(); } }
小 结 • 介绍了C#数据类型的引用类型、装箱和拆箱 • 介绍了C#的运算符