1 / 24

第 2 章 数据类型与流程控制

第 2 章 数据类型与流程控制. 2.2.2 引用类型 C# 语言中的另一大数据类型是引用类型。 “ 引用 ” 指的是该类型的变量不是直接存储所包含的实际数据,而是存储实际数据的地址。 C# 语言中的引用类型有 4 种,类、委托、接口和数组。 1 、类 类是面向对象编程的基本单位,是一种包含数据成员、函数成员和嵌套类型的数据结构。类的数据成员有常量、域和事件。函数成员包括方法、属性、索引指示器、运算器、构造函数和析构函数。类和结构同样都包含了自己的成员,但它们之间最主要的区别在于:类是引用类型,而结构是值类型。

claudia-gay
Download Presentation

第 2 章 数据类型与流程控制

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第2章 数据类型与流程控制 2.2.2 引用类型 C#语言中的另一大数据类型是引用类型。“引用”指的是该类型的变量不是直接存储所包含的实际数据,而是存储实际数据的地址。C#语言中的引用类型有4种,类、委托、接口和数组。 1、类 类是面向对象编程的基本单位,是一种包含数据成员、函数成员和嵌套类型的数据结构。类的数据成员有常量、域和事件。函数成员包括方法、属性、索引指示器、运算器、构造函数和析构函数。类和结构同样都包含了自己的成员,但它们之间最主要的区别在于:类是引用类型,而结构是值类型。 类支持继承机制,通过继承,派生类可以扩展基类的数据成员和方法,进而达到代码重用和设计重用的目的。

  2. 第2章 数据类型与流程控制 2.2.2 引用类型 2、委托 委托是指引用方法的类型,它实际上相当于C++语言中的函数指针原型,但与指针不同的是,委托在C#语言中是安全的,它允许实例化和调用类的静态方法,也可以调用类的指定实例的方法。在声明委托类型时,只需要指定委托指向的原型的类型,它不能有返回值,也不能带有输出类型的参数。

  3. 第2章 数据类型与流程控制 2.2.2 引用类型 3、接口 接口是一组包含了方法的数据结构。通过这组数据结构,可以在代码中调用组件对象的功能。接口可以从父接口中继承,但实际含义是说明继承,而不是实现性继承。它的实现需要通过类或结构来完成。接口的成员可以是方法、属性、索引指示器和事件,但不能是常量、域、操作符和构造函数,而且不能包含任何静态成员。

  4. 第2章 数据类型与流程控制 2.2.2 引用类型 4、数组 数组和结构不同,结构一般用于存储多种类型的数据,而数组则用于存储同一种类型的数据。数组是一种引用类型,而不是值类型。数组是按照数组名、数据元素的类型和维数来描述的。C#语言中可以有一维数组和多维数组,多维数组中又可以分为矩形数组和交错数组。 (1)数组的声明 C#语言可以在声明时不对数组进行初始化,需要使用数组时再在程序中动态地指定其大小,如表2-6所示。

  5. 表2-6 数组的声明语法 4、数组 (1)数组的声明

  6. 例如: 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)数组的声明

  7. 访问共有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)数组的使用

  8. [例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

  9. (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];

  10. //二维矩形数组 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(); }

  11. //输出二维交错型数组的元素 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

  12. 第2章 数据类型与流程控制 2.2.3 值类型之间的数据交换 值类型之间的数据交换可以相互转换。如果仅仅是数据表示范围不同的数据类型之间的转换,例如,int型和long型的数据转换,比较常用的两种转换方式是:隐式转换与显示转换。如果是不同值类型之间的转换,则可以使用Convert类。 1、隐式转换 隐式转换就是系统默认的、不需要加以声明就可以进行的转换,如从int类型转换到long类型: int k=1; long i=2; i=k; //隐式转换 在进行隐式的类型转换时,其实就是从低精度、小范围的数据类型转换为高精度、大范围的数据类型。这种转换一般没有问题,这是因为大范围类型的变量具有足够的空间存放小范围类型的数据。表2-7中列出了C#语言支持的隐式转换的类型。

  13. 表2-7 隐式转换类型

  14. 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还要大,而语句中又使用了强制的类型转换,系统对这种转换不会报错,会强制执行,从而导致数据溢出,发生错误。

  15. 2、显式转换 如果的确需要使用显式的类型转换,但又不知是否会发生溢出而导致数据错误,可以使用checked运算符来检查数据类型是否安全。如上例,可以写为: long r=3000000000; int i=checked(int)r; 在这种情况下,如果出现溢出,系统就会在运行时抛出一个溢出异常,不会使程序继续运行。 另外,C#语言中还提供了一个Convert类,也可以用于各种值类型之间的转换,有关Convert类的使用方法将在第3章介绍。

  16. [例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

  17. 2.2.4 装箱和拆箱 装箱和拆箱功能使得C#语言中所有的值类型都可以与object类型实现双向转换。 1、Object类 Object类是所有其他类型的基类,C#语言中的所有类型都直接或间接地从Object类中继承。因此,可以使用Object类引用绑定任何特定子类型的对象。 值类型与Object类型之间的转换有什么意义呢?举个例子,在程序中可以直接这样写: string s=(10).ToString(); 数字10只是一个堆栈上的4字节的值,怎么能实现调用它上面的方法呢?实际上,C#语言是通过装箱和拆箱操作来实现的,即先把10转换为引用类型,然后再调用引用类型的方法来实现指定的功能。

  18. 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; //拆箱操作 可以看出来,拆箱正好是装箱的逆过程,但必须注意的是,装箱和拆箱必须遵循类型兼容的原则。

  19. 2.2.5 运算符与优先级 C#语言有三大类运算符。 一元运算符:带有一个运算对象,例如,i++。 二元运算符:带有两个运算对象,例如,x+y。 三元运算符:带有3个运算对象,例如, <条件>?<条件成立时结果表达式>:<条件不成立时结果表达式>。 5>3?58:98 //结果为58 表2-8列出了常用运算符及其相关说明。

  20. 表2-8 常用运算符

  21. 当一个表达式包含多个操作符时,表达式的值就由各操作符的运算优先级决定。表2-9列出了常见运算符的优先级。

  22. 当一个操作数出现在两个有相同优先级的操作符之间时,操作符按照出现的顺序由左至右执行。如果无法确定操作符的有效顺序,则可以在编程时采用括号“()”进行指定,从而保证运算的顺序正确无误,也使得程序一目了然。当一个操作数出现在两个有相同优先级的操作符之间时,操作符按照出现的顺序由左至右执行。如果无法确定操作符的有效顺序,则可以在编程时采用括号“()”进行指定,从而保证运算的顺序正确无误,也使得程序一目了然。

  23. //表达式举例 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(); } }

  24. 小 结 • 介绍了C#数据类型的引用类型、装箱和拆箱 • 介绍了C#的运算符

More Related