1 / 64

Visual C#.NET 程序设计

Visual C#.NET 程序设计. 第 8 章 维护数据 ( 二 ). 学习和实践的目标. 需求分析要求:增加、删除、修改与学生成绩相关的基础数据,即学生、学年、课程、教师、成绩比例和操作员。 本章将充分利用对象的继承性和多态性完成所有基础数据的增加、修改和删除。. 实现目标的知识点. 数组 跳转和循环控制 数据类型转换. 8.1 实现目标的步骤. 利用对象的继承性和多态性维护数据的步骤如图 8-1 所示。. 8.2 数组与循环控制处理.

kevina
Download Presentation

Visual C#.NET 程序设计

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. Visual C#.NET程序设计 第8章 维护数据(二)

  2. 学习和实践的目标 • 需求分析要求:增加、删除、修改与学生成绩相关的基础数据,即学生、学年、课程、教师、成绩比例和操作员。 • 本章将充分利用对象的继承性和多态性完成所有基础数据的增加、修改和删除。

  3. 实现目标的知识点 • 数组 • 跳转和循环控制 • 数据类型转换

  4. 8.1 实现目标的步骤 • 利用对象的继承性和多态性维护数据的步骤如图8-1所示。

  5. 8.2 数组与循环控制处理 • 数据及其处理总是贯穿在应用程序的整个开发过程中。相关的数据可以聚合成集。通过数据集的集中处理,可以极大地提高数据处理的灵活性和效率。 8.2.1 数组 • 以System.Array为基类型的数组是一种包含若干元素的数据结构,是特殊的数据集合。 • 每个数组中包含的若干个元素都具有相同的数据类型,可通过一个统一的数组变量名和下标(索引)来唯一地确定数组中的元素以进行访问。 • C#中的数组有一维数组、多维数组和交错数组。

  6. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • 一维数组的声明格式如下: • 数组类型[] 数组变量; • 数组类型可以为.NET平台下支持的任意数据类型,如:Int16、 Int32和Int64等,它们都处于System命名空间中。假设事先已引入System命名空间。 • 如: • Int32[] a;

  7. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • 数组类型属于引用类型,因此数组变量的声明只是为数组实例的引用留出空间,实际的数组实例在运行时使用new 运算符动态创建。如: • a=new Int32[10]; • 以上语句才会使数组a成为实际上的、物理上存在的整型数组,数组a将会包含10个Int32型的元素。

  8. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • new 运算符从真正意义上创建了数组,同时也指定了新数组实例的长度 (length),它在该实例的生存期内是固定不变的。 • 数组元素的索引范围从 0 到 Length - 1。 • new 运算符自动将数组的元素初始化为它们的默认值,例如将所有数值类型初始化为零,将所有引用类型初始化为 null。

  9. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • 下面的控制台应用程序创建并初始化了一个 Int32 类型的一维数组,同时还在控制台上输出该数组中的内容: • using System; • class Test • { • static void Main() • { • Int32[] a = new Int32[10]; • for (Int32 i = 0; i < a.Length; i++) a[i] = i * i;

  10. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • for (Int32 i = 0; i < a.Length; i++) • { • Console.Write ("a["+i+"] = "+a[i]+””); • } • } • } • 所生成的输出如下: • a[0]=0 a[1]=1 a[2]=4 a[3]=9 a[4]=16 a[5]=25 a[6]=36 a[7]=49 a[8]=64 a[9]=81

  11. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • new 运算符还允许使用数组初始值设定项,以指定数组元素的初始值。数组初始值设定项是在一个位于定界符 {} 之间的表达式列表。下面的示例分配并初始化具有三个元素的 Int32[]: • Int32[] a = new Int32[] {1, 2, 3};

  12. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • 注意数组的长度是从 {} 之间的表达式个数推断出来的。对于局部变量和字段声明,可以进一步简写,不必再次声明数组类型。例如: • Int32[] a = {1, 2, 3}; • 前面的两个示例都等效于下面的示例: • Int32[] a = new Int32[3]; • a[0] = 1; • a[1] = 2; • a[2] = 3;

  13. 8.2 数组与循环控制处理 8.2.1 数组 1.一维数组 • 当一个数组创建表达式既包含显式维度长度,又包含数组初始值设定项时,长度必须是常量表达式,同时各嵌套级别的元素数目必须与相应的维度长度相匹配。参见以下示例: • Int32 i = 3; • Int32[] x = new Int32[3] {0, 1, 2}; // 正确 • Int32[] y = new Int32[i] {0, 1, 2}; // 错误, i 不是常量 • Int32[] z = new Int32[3] {0, 1, 2, 3}; // 错误, 维度长度和一个数组初始值设定项不匹配

  14. 8.2 数组与循环控制处理 8.2.1 数组 2.多维数组 • 数组类型的维数也称为数组类型的秩 (rank),它是数组类型方括号之间的逗号个数加上 1。例如: • Int32[,]a1 = new Int32[10, 5]; //分配一个二维数组 • Int32[,,]a2 = new Int32[10, 5, 2]; //分配一个三维数组 • a1 数组包含 50 (10 × 5) 个元素, a2 数组包含 100 (10 × 5 × 2) 个元素。 • 多维数组的初始值设定项必须具有与数组维数同样多的嵌套级别。最外面的嵌套级别对应于最左边的维度,而最里面的嵌套级别对应于最右边的维度。

  15. 8.2 数组与循环控制处理 8.2.1 数组 3.交错数组 • 数组的元素类型不仅可以是.NET平台下支持的任意数据类型任意类型,还可以是数组类型。数组元素的类型为数组时称之为交错数组 (jagged array),此时元素数组的长度不必全都相同。下面的示例分配一个由 Int32 数组组成的数组: • Int32[][] a = new Int32[3][]; • a[0] = new Int32[10]; • a[1] = new Int32[5]; • a[2] = new Int32[7];

  16. 8.2 数组与循环控制处理 8.2.1 数组 3.交错数组 • a[0] = new Int32[]{ 2,4,6,8,10,12,14,16,18,20 }; //10个整数组成的数组 • a[1] = new Int32[]{ 1,3,5,7,9 }; //5个整数组成的数组 • a[2] = new Int32[]{ 11,22,33,44,55,66,77 }; //7个整数组成的数组。

  17. 8.2 数组与循环控制处理 8.2.2 循环控制结构 • 循环控制结构可以用于重复执行嵌入语句。C#中的循环(迭代)语句有: • while语句 • do语句 • for语句 • foreach语句

  18. 8.2 数组与循环控制处理 8.2.2 循环控制结构 1.while 语句 • while 语句按不同条件不执行或至少执行一次语句块。while 语句的一般格式为: • while ( 布尔表达式 ) • { • 语句块; • } • while 语句按下列规则执行: ① 计算布尔表达式。 ② 当布尔表达式值为true时,执行while语句中的语句块,然后程序转到①。 ③ 当布尔表达式值为 false时,结束循环。

  19. 8.2 数组与循环控制处理 8.2.2 循环控制结构 1.while 语句 • 下面的控制台应用程序,利用while语句求1+2+3+…+10,并在控制台上输出其和。代码如下: • using System; • class Sum • { • static void Main() • { • Int32 num=1,sum=0; • while (num<11) • { • sum=sum+num; • num++; • } • Console.WriteLine("1+2+3+...+10 ="+sum); • } • } 输出结果如下: 1+2+3+...+10 =55

  20. 8.2 数组与循环控制处理 8.2.2 循环控制结构 2.do 语句 • do 语句按不同条件至少执行一次或多次语句块。do 语句的一般格式为: • do • { • 语句块; • } • while (布尔表达式 ) ; • do 语句按下列规则执行: ① 执行语句块一次。 ② 计算布尔表达式的值,当值为true时,程序转到①;否则,结束循环。

  21. 8.2 数组与循环控制处理 8.2.2 循环控制结构 • 下面的控制台应用程序,利用do…while语句求1+2+3+…+10,并在控制台上输出其和。代码如下: • using System; • class Sum • { • static void Main() • { • Int32 num=1,sum=0; • do • { • sum=sum+num; • num++; • } • while (num<11); • Console.WriteLine("1+2+3+...+10 ="+sum); • } • } 输出结果同while语句。

  22. 8.2 数组与循环控制处理 8.2.2 循环控制结构 3.for 语句 • for 语句计算一个初始化表达式,然后,当某个条件为真时,重复执行相关的嵌入语句并计算一个迭代表达式序列。for 语句的一般格式为: • for(初始化表达式 ; 终止条件布尔表达式 ; 步进语句表达式) • { • 语句块; • } • 其中初始化表达式是为循环变量赋初值,可以有1个或多个,若有多个则用逗号隔开;终止条件布尔表达式是用来决定是否执行语句块;步进语句表达式是按规律改变初始表达式中循环变量的值。这三个表达式都是可选的,缺省某个表达式时,其后的“;”不能省。

  23. 8.2 数组与循环控制处理 8.2.2 循环控制结构 3.for 语句 • 下列代码表达了三个表达式都缺省的情况: • for(;;) • { • 语句块; • } • for 语句按如下规则执行: • ① 执行初始化表达式,为循环变量赋初值。 • ② 若没有终止条件布尔表达式,或终止条件布尔表达式值为true时,则直接执行大括号中的语句块,程序转向③;否则,结束循环。 • ③ 执行步进语句表达式,程序转向②。

  24. 8.2 数组与循环控制处理 8.2.2 循环控制结构 3.for 语句 • 下面的控制台应用程序,利用for语句求1+2+3+…+10,并在控制台上输出其和。代码如下: • using System; • class Sum • { • static void Main() • { • Int32 num,sum; • for(num=1,sum=0;num<11;num++) • { • sum=sum+num; • } • Console.WriteLine("1+2+3+...+10 ="+sum); • } • } 输出结果同while语句。

  25. 8.2 数组与循环控制处理 8.2.2 循环控制结构 4.foreach 语句 • foreach 语句用于遍历一个集合的元素,并对该集合中的每个元素执行一次相关的语句块。foreach 语句的一般格式为: • foreach ( 类型标识符 标识符 in 表达式 ) • { • 语句块; • } • 其中类型标识符和标识符用来声明变量,表达式的类型必须是集合类型,如果该表达式的值为 null,则将引发异常。每执行一次语句块,循环变量就依次取集合中的一个元素代入其中。

  26. 8.2 数组与循环控制处理 8.2.2 循环控制结构 4.foreach 语句 • 下面的控制台应用程序,用于按照元素的顺序打印出一个二维数组中的各个元素的值。代码如下: • using System; • class Test • { • static void Main() • { • Double[,] values = {{1.2, 2.3, 3.4, 4.5},{5.6, 6.7, 7.8, 8.9}}; • foreach (Double elementValue in values) • Console.Write(" " + elementValue); • Console.WriteLine(); • } • } 输出结果如下: 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9

  27. 8.2 数组与循环控制处理 8.2.3 跳转语句 • 跳转语句用于无条件地在程序间转移控制权。C#中的跳转语句有: • break语句 • continue语句 • goto 语句 • return 语句 • throw 语句 • 跳转语句会将控制转到某个位置,这个位置就称为跳转语句的目标 (target)。 • 当一个跳转语句出现在某个块内,而该跳转语句的目标在该块之外时,就称该跳转语句退出该块。虽然跳转语句可以将控制转到一个块外,但它永远不能将控制转到一个块的内部。

  28. 8.2 数组与循环控制处理 8.2.3 跳转语句 1.break 语句 • break 语句直接退出所属的switch、while、do、for 或 foreach 语句。当程序遇到这一语句后,执行紧接在被终止执行的语句后面的语句。通常break语句总是与if语句联在一起。即满足条件时便跳出循环。 • 当多个 switch、while、do、for 或 foreach 语句彼此嵌套时,break 语句只应用于最里层的语句。若需要穿越多个嵌套层,可使用 goto 语句。 • break 语句不能退出 finally 块。当 break 语句出现在 finally 块中时,该 break 语句的目标必须位于同一个 finally 块中,否则将发生编译时错误。块外,但它永远不能将控制转到一个块的内部。

  29. 8.2 数组与循环控制处理 8.2.3 跳转语句 1.break 语句 • 下面的控制台应用程序计算1~100之间的和,当数超过100时终止循环。代码如下: • using System; • class Sum • { • static void Main() • { • Int32 num=1,sum=0; • while (true) • { • sum=sum+num; • num++; • if (num>100) break; • } • Console.WriteLine("1+2+3+...+100 ="+sum); • } • } 输出结果如下: 1+2+3+...+100 =5050

  30. 8.2 数组与循环控制处理 8.2.3 跳转语句 2.continue 语句 • continue 语句直接结束封闭它的 while、do、for 或 foreach 语句的本次循环,进入下一轮循环。它与前面提到的break语句不同,它并不终止整个循环的执行,而仅仅终止当前这一次循环的运行。 • 如果 continue 语句不是由 while、do、for 或 foreach 语句所封闭的,则发生编译时错误。 • 当多个 while、do、for 或 foreach 语句互相嵌套时,continue 语句只应用于最里层的那个语句。若需要穿越多个嵌套层,可使用 goto 语句。 • continue 语句不能退出 finally 块。当 continue 语句出现在 finally 块中时,该 continue 语句的目标必须位于同一个 finally 块中,否则将发生编译时错误。

  31. 8.2 数组与循环控制处理 8.2.3 跳转语句 2.continue 语句 • 下面的控制台应用程序计算数1~100之间的偶数和。代码如下: • using System; • class Sum • { • static void Main() • { • Int32 num,sum=0; • for(num=1;num<101;num++) • { • if (num%2!=0) continue; • sum=sum+num; • } • Console.WriteLine("1到100之间的偶数和为 "+sum); • } • } 输出结果如下: 1到100之间的偶数和为 2550

  32. 8.2 数组与循环控制处理 8.2.3 跳转语句 3.goto 语句 • goto 语句将控制无条件的转移到由标签标记的语句。它能用来跳出循环和switch语句。 • 如果当前函数成员中不存在具有给定名称的标签,或者如果 goto 语句不在该标签的范围内,则发生编译时错误。标号与goto语句必须处在同一个函数中。此规则允许使用 goto 语句将控制转移“出”嵌套范围,但是不允许将控制转移“进”嵌套范围。 • goto 语句不能退出 finally 块。当 goto 语句出现在 finally 块中时,该 goto 语句的目标必须位于同一个 finally 块中,否则将发生编译时错误。

  33. 8.2 数组与循环控制处理 8.2.3 跳转语句 3.goto 语句 • 下面是一个控制台应用程序示例: • using System; • class Test • { • static void Main(string[] args) • { • string[,] table = {{"Red", "Blue", "Green"},{"Monday", "Wednesday", "Friday"}}; • foreach (string str in table) • { • int row, colm; • for (row = 0; row <= 1; ++row) • for (colm = 0; colm <= 2; ++colm) • if (str == table[row,colm]) • goto done;

  34. 8.2 数组与循环控制处理 8.2.3 跳转语句 3.goto 语句 • Console.WriteLine(“{0} 未找到”, str);//显示str的内容未找到 • continue; • done: • Console.WriteLine("在[{1}][{2}]位置找到{0}", str, row, colm); • } • } • } • 输出结果如下: • 在[0][0]位置找到Red • 在[0][1]位置找到Blue • 在[0][2]位置找到Green • 在[1][0]位置找到Monday • 在[1][1]位置找到Wednesday • 在[1][2]位置找到Friday

  35. 8.2 数组与循环控制处理 8.2.3 跳转语句 4.return 语句 • return 语句将控制返回到包含return 语句的函数成员的调用方。 • 若函数成员没有返回类型,则return语句后不带任何表达式;或函数成员有返回类型,则return语句后的表达式的计算结果,必须与函数成员返回类型一致。 • return 语句出现在 finally 块中会造成编译时错误。 • 下面是一个控制台应用程序示例: • using System; • class Test • { • static Int64 sum(Int32 num)

  36. 8.2 数组与循环控制处理 8.2.3 跳转语句 4.return 语句 • { • Int64 mysum=0; • for (Int32 i = 1; i <=num; i++) • mysum = mysum + i; • return mysum; • } • static void Main(string[] args) • { • Console.WriteLine("从1到100的和为 "+sum(100)); • } • } • 输出结果如下:从1到100的和为 5050 5.throw语句 • throw 语句引发一个异常。

  37. 8.3 数据类型的转换 • 类型转换是将数据从一种类型更改为另一种类型的过程。例如,可以将字符串“1234”转换为一个数字。可以将任意类型的数据转换为 String 类型。 • 某些类型转换永远不会成功。例如,字符串"张三"不能转换为整型数据。

  38. 8.3 数据类型的转换 1.基本概念 • 类型转换有可能扩大,也有可能收缩。 • 扩大转换就是指将数据类型A的值转换为数据类型B,并且保证数据类型B可以容纳数据类型A的任何可能值,例如,转换Int32型为Int64型,转换派生类型为基类型。 • 收缩转换就是指将数据类型A的值转换为数据类型B,但数据类型B无法容纳数据类型A的某些可能值,例如,转换Int64型为Int32型,转换基类型为派生类型。

  39. 8.3 数据类型的转换 1.基本概念 • 扩大转换永远不会溢出,并且总是成功的;而收缩转换必然往往伴有信息的丢失,并有可能失败。 • 两种转换类型都可以是显式(使用数据类型标识符)或隐式(不使用数据类型标识符)的。例如: • Int32 a = 123; • Int64 b = a; // 隐式转换 • Int32 c = (Int32) b; // 显式转换

  40. 8.3 数据类型的转换 1.基本概念 • 有效的显式转换即使会导致信息的丢失,也始终是成功的。而隐式转换只有在转换过程不丢失数据的情况下才能成功;否则,它们就会失败并生成编译或运行时错误。 • .NET类库中的 Form 窗体类有一个属性Controls,这是一个集合,其中元素是窗体上的所有控件,如:TextBox。窗体上的控件都以Control为基类。

  41. 8.3 数据类型的转换 1.基本概念 • 下面代码将窗体上的一般控件显式收缩转换为TextBox控件。 • foreach(Control ctl in Controls) • { • //从Control基类显式转变为TextBox派生类 • TextBox tx = (TextBox)ctl; • } • 执行中许多非TextBox控件向TextBox控件转换时会失败。

  42. 8.3 数据类型的转换 1.基本概念 • 当原始数据类型在目标转换类型中没有明显的对应类型时,就会发生丢失数据的转换。例如,字符串"Fred"不能转换为一个数字。在这些情况下,类型转换函数将返回一个默认值。对于字符串类型,默认值为"";对于整型类型,默认值为数字 0。 • 常用的ToString方法就是显式转换的典型代表,因为它是所有数据类型的根类object的方法,所以所有数据类型都可以向字符串类型转换。

  43. 8.3 数据类型的转换 2.Convert类 • Convert是一个专用来将一个基本数据类型转换为另一个基本数据类型的类,因为是静态类,不需要实例化就可以直接使用。 • 例如: • Int64 I = 123; • Int32 i = Convert.ToInt32(I);

  44. 8.3 数据类型的转换 3.装箱和拆箱 • 装箱和拆箱的概念是 C# 的类型系统的核心。它在值类型和引用类型之间的架起了一座桥梁,使得任何值类型的值都可以转换为 object 类型的值,反过来转换也可以。从值类型转换为引用类型称为装箱,反之,称为拆箱。 • 装箱和拆箱使我们能够统一地来考察类型系统,其中任何类型的值最终都可以按对象处理

  45. 8.3 数据类型的转换 3.装箱和拆箱 • 下面是装箱和拆箱转换的示例,代码如下: • Int32 i = 10; //i是值类型 • object o = i; //装箱 • i = (Int32)o; //拆箱 • MessageBox.Show(i.ToString());//整型数转换成字符串 • 装箱操作如图8-2所示,拆箱操作如图8-3所示。

  46. o:object i:Int32 10 i:Int32 10 拆箱 装箱 i:Int32 10 Int32 10 o:object 8.3 数据类型的转换 3.装箱和拆箱 • 图8-2装箱操作 图8-3拆箱操作

  47. 8.3 数据类型的转换 3.装箱和拆箱 • 一个装箱操作包括两个步骤:首先分配一个对象实例,然后将值类型的值复制到该实例中。 • 一个拆箱操作包括两个步骤:首先检查对象实例是否为给定值类型的一个装了箱的值,然后将该值从实例中复制出来。

  48. 8.4 改造ShowDialog方法 我们已经建立了数据维护对象体系,如图8-4所示。

  49. 8.4 改造ShowDialog方法 • 实现了frm增改学生的ShowDialog方法。 • 类似地,要为frm增改课程等实现ShowDialog方法。不仅工作量较大,且容易出错,将来也不利于进行代码维护。 • 若能在frm增改中实现ShowDialog方法,则可以惠及其派生类,起到“一劳永逸”的功效。

  50. 8.4 改造ShowDialog方法 8.4.1 提示必要信息 • 在frm增改中实现ShowDialog方法所面临的最大问题是:不知道其派生类中需要处理的输入控件。而处理的关键是要抓住被处理的控件。 • 窗体对象包含有一个控件集合Controls,控件集合Controls中包含了窗体上所有的控件(Control),如TextBox和DateTimePicker控件等。如果能对Controls中所有的Control进行遍历,就能进行适当的处理了。

More Related