导图社区 面向对象的程序设计1-4章
面向对象的程序设计1-4章面向对象的可视化编程知识总结,包括C#概述、C#程序设计基础、C#程序的流程控制、面向对象程序设计入门、面向对象的高级程序设计等等。
编辑于2022-05-10 22:40:10面向对象的可视化编程
C#概述
C#简介
C#语言的发展
C#是一种最新的、面向对象的编程语言
C#是从C和C++语言演化而来
C#与.Net Framework同步发展,目前由很多版本
.Net Framework
微软开发的软件框架
主要组件
公共语言运行时(CLR)
为.Net Framework编写的程序在公共语言运行时(CLR)的软件环境中执行
.Net Framework的基础,是应用程序的托管环境
在公共语言运行库基础之上运行的应用程序称为托管应用程序
传统的直接在操作系统基础上运行的应用程序称为非托管应用程序
BCL基础类库
.Net Framework类库是一个综合性的面向对象的可重用类型集合
ADO.NET、ASP.NET、WCF、Azure、Workflow框架等
ADO.NET时.Net Framework提供的微软新一代的面向对象的数据处理技术,利用它可以简便、快捷地开发数据库应用程序
ASP.NET时.Net Framework提供地全新的Web应用程序开发技术
XML Web Service是一种能够在Internet环境中直接调用的组件。
C#语言的特点
精确、简单、类型安全、面向对象
良好的可扩展性,具有生成持久系统级组件的能力
利用.Net Framework的通用类型系统能与其他程序设计语言交互操作,能跨语言、跨平台互相调用
支持多种组件服务,实现了组件之间的跨互联网调用
允许自定义数据类型,以扩展元数据
增强了开发者的效率,同时也致力于消除编程种可能导致严重结果的错误
C#程序的开发环境
Visual Studio .Net
主要文件类型
.sln
Visual Studio .Net解决方案文件
.csproj
Visual C#项目文件
.cs
Visual C#源文件
.resx
资源文件
.aspx
Web窗体文件
.asmx
XML Web服务文件
C#程序特点
必须借助Net Framework类库实现
必须定义类
C#程序的源代码必须封装到类中,一个程序至少包括一个自定义类
类的代码主要由方法组成
C#程序种的方法由方法头部、方法体组成
方法的头部:方法的第一行,包括返回值类型、方法名、形参名及形参类型的说明
方法体:使用一对大括号{}括起来,通常包括声明语句和执行语句
C#程序的语句
每个语句必须以分号结尾
一行可以书写多条语句,一条语句也可以写在多行
C#程序的输入与输出操作
本身没有输入输出语句
控制台程序必须借助类库种的Console类的方法来完成输入输出操作
Window应用程序和Web应用程序必须借助类库的标签Label、文本框TextBox等空间来实现输入输出
C#程序的注释
使用//或/*……*/添加注释
C#程序设计基础
常量与变量
常见的数据类型
int(整型)
double(双精度)
char(字符型)
用于存储单个字符
bool(布尔)
true/false
string(字符串)
常量(运行时其值始终不变)
整型常量
有符号的整型常量
-8
无符号整型常量
8U或8u
长整型常量
8L或8l
浮点型常量
单精度
8.3F
双精度
8.3D
小数型常量
后面必须添加m或M标记
8.3M
字符型常量
是一个标准的Unicode字符,用单引号标记
'8'
转义字符常量
\n换行
\'单引号
\"双引号
\0空字符
\\反斜线符\
布尔型常量
只有true和false
字符串常量
若干个Unicode字符组成的字符序列,用双引号标记
"8"
在字符串常量中如果需要包括特殊字符,需要使用转义字符
变量(运行时其值可以被改变)
概念
变量名
只能由字母、数字、下划线_组成
不能由数字开始
不能用C#保留字
变量值
系统自动为变量分配内存单元,用来存储变量的值
程序通过变量名来引用变量的值
定义变量
类型标识符 变量名1, 变量名2, ... ;
int x, y, z;
变量定义必须放在变量使用之前
C#允许使用保留字var来定义变量
变量的数据类型就是初始值的数据类型,因此不需要指定变量的数据类型
变量的初始化
类型标识符 变量名[=初值1], 变量名[=初值2],... ;
int a=12, b=-24, c=10;
也可以先定义再赋值
int a, b, c; a=b=c=1;
C#的数据类型
简单类型
唯一有取值的类型
整数类型
char为字符型,表示一个Unicode字符的编码
浮点型
一般用来表示一个有确定值的小数
float、Double
出于计算机运算速度和对资源要求考虑,在对精度要求不高的情况下,尽量使用单精度型。
小数型decimal
精度比浮点型高
布尔型
枚举类型enum
实质是使用符号来表示一组相互关联的数据
enum Months { Jan, Feb, Mar, Apr, May, Jun, Jul, Augt, Sep, Oct, Nov, Dec };
注意
枚举元素的数据值、个数一旦声明不能在程序运行中更改
默认情况下,枚举元素的值是一个整数,第一个枚举数的值是0,后面依次递增1, 如要改变默认规则,则重写枚举元素的值即可
enum MyEnum {a=101, b, c, d=201, e, f}
结构类型struct
C#内置的结构型主要有:DateTime、TimeSpan等
包括数据成员、方法成员
struct Student { public int id; public string name; public int age; public char sex; }
Student是结构性的名称,id、name、sex、age是结构类型的数据成员
使用方法
结构型变量.结构型成员
Student a; //定义结构型变量a a.id = 1001; //为a的成员变量id赋值
数据类型转换
隐式转换(一般在不同类型的数据进行混合运算的时候发生)
如果参与运算的数据类型不相同,则先转换为同一类型
转换时按数据长度增加的方向进行
以下代码会出现错误: int x = 56; uint y = x;
所有的浮点运算都是以双精度进行的
byte型和short型参与运算时,必须先转换成int型
char可以隐式转换成其他类型,但不存在从其他类型到char类型的隐式转换
显式转换(需要明确要求编译器完成的转换)
显示转换可能造成精度的损失
(类型说明符) (带转换的数据)
待转换的数据不是单个变量时,类型说明符和待转换的数据都必须加圆括号
(int)(x+y)
double d = 12.5; int a = (int)d; 执行后,a的值为12,小数部分丢失
C#允许使用System.Convert类提供的类型转换方法来转换数据类型
byte x=10, y=100; byte z = Convert.ToByte(x+y); char w = Convert.ToChar(z+20); DateTime date = Convert.ToDateTime("2011-10-1");
C#内置的简单类型均自带Parse方法转换字符串
int a = int.Parse("2011.50"); //输出为2011 float b = float.Parse("2011.50"); //输出为2011.50
C#内置的ToString方法可以将i按量转化为字符串
int a = 2011; string str = a.ToString();
运算符与表达式
算数运算符(用于数值运算)
二目运算符
加+、减-、乘*、除/、取余数%
单目运算符
自增++、自减--
具有右结合性(优先同运算符右边的变量结合)
在变量的左边时,为前置计算,先自增自减再使用变量的值
int num1=5; num2=++num1; 此时num1=6,num2=6
在变量的右边时,为后置计算,先使用变量的值再自增自减
int num1=5; num2=num1++; 此时num1=6,num2=5
赋值运算符
简单赋值运算符
=
变量=表达式
赋值号右边可以是变量、常量或表达式,左边只能是变量
如果复制好两边的数据类型不同,系统将自动先将赋值号右边的类型转换为左边的类型再赋值
不能把右边长度更大的数值类型隐式转换并赋值给左边数据长度更小的数值类型
错误的语句: short a = 1, b = 2; short c = a+b;
复合赋值运算符
+=、-=、*=、/=、%=等
变量 双目运算符= 表达式 (变量=变量 双目运算符 表达式)
a*=y+1 等价于a=a*(y+1)
关系运算符
优先级低于算术运算符
==、!=、<、>、<=、>=
输出结果只能是布尔型值
i=4, j=5 则关系表达式i !=j输出为true
逻辑运算符
优先级低于关系运算符的优先级,但高于赋值运算符的优先级
&&或& 逻辑与
&&和&的主要区别:当第一个操作为false时,前者不再计算第二个操作数的值
设置i=5,j=4 i != j && i >=j 结果为true
||或| 逻辑或
!逻辑非
^逻辑异或
当且仅当只有一个操作数为true时,结果才为true。
运算符优先级
( )→++、--、!→*、/、%→+、-→>、<、>=、<=→==、!=→&&→||→=、+=、*=、/=、%=、-=
数组和字符串
由若干变量组成的集合, 数组元素可以是任何类型,但没有名称,只能通过索引来访问 数组有“秩”
一维数组
声明和创建
一般形式
数组类型[]数组名=new 数组类型[数组长度]
int [ ] a = new int[5];
先声明后创建
int [ ] a; a = new int[5];
使用var声明
var a = new int[5];
初始化
创建时初始化
int[ ] a = new int [5] {1,2,3,4,5}; //[5]里的5可省略 int[ ] a = new int [5] {1,2,3}; //错误
可简写 int[ ] a = {1,2,3,4,5};
使用var var[ ] a = new [ ] {1,2,3,4,5}; //a为整数型数组
先声明后初始化
int[ ] a; a = new int[ ] {1,2,3,4,5};
这种情况下不能采用简写形式
int[ ] a; a = {1,2,3,4,5}
先创建后初始化
int [ ] a = new int[2]; a[0]=1; a[1]=2;
可实现结构体数组元素的初始化
Student[ ] s = new Student[2]; s[0].stuNo = 1001; s[0].stuName = "郭靖"; s[1].stuNo = 1002; s[1].stuName = "杨过";
使用
每一个数组元素相当于一个普通的变量
a[4]=5 //为数组a的第5个元素赋值为5
操作
C#的数组类型是从抽象基类型System.Array派生的。
Array的方法类成员Clear(清除)、Copy(复制)、Sort(排序)、Reverse(反转顺序)、IndexOf(从左至右查找数组元素)、LastIndexOf(从右往左查找)、Resize(更改数组长度)
Sort、Reverse、IndexOf、LastIndexOf、Resize只能用于一维数组
多维数组
声明和创建
声明和创建一个5×4×3共60个元素的三维数组a int[ , , ] a = new int[5, 4, 3];
使用var创建 var a = new int[5, 4, 3];
初始化
同一维度的初始值放在一对花括号{}中
int [ , ] a = new int[2,3] { {1,2,3} , {4,5,6} }; int [ , ] a = new int[2,3] {1,2,3,4,5,6};
可以省略维度长度列表,但逗号不能省略
int[ , ] a = new int[ , ] { {1,2,3} , {4,5,6} };
可以使用简写
如果先声明再初始化就不能简写
int [ , ] a; a = { {1,2,3} , {4,5,6} };
int [ , ] a = { {1,2,3} , {4,5,6} };
可以用var
var d = new [ , ] { {1,2,3} , {4,5,6} };
多维数组不允许部分初始化
int [ , ] a = new int[2,3] { {1} , {4} };
使用
a[0,0] = 50; //将a[0,0]赋值为50
数组型的数组
由若干个数组构成的数组
声明和创建
int[ ] [ , ] a = new int[2] [ , ];
在声明数组型数组时,不能指定子数组的长度
初始化
同样有创建时初始化、先声明后初始化、先声明后初始化
对于数组型数组来说,C#允许子数组的长度不相同
先声明后初始化更加直观 int[ ] [ ] a = new int[2] [ ]; a[0]=new int[3]{1,2,3}; a[1]=new int[3]{4,5,6};
引用
a[0][0]表示第一个数组的第一个数组元素
字符串string
声明
string name = "张三丰";
空字符串的声明
string str1 = ""; string str2 = String.Empty;
由一个或多个空白字符串组成的字符串不是空字符串
运算
使用+来连接
C#字符串是不可变的,字符串一旦创建,其内容不能更改,使用+=后,变量指向了新字符串,原来的字符串依然存在只是不使用了
允许使用==、!=来比较两个字符串的字符是否相同
C#的字符串可以看成一个字符数组,因此,C#允许通过索引来提取字符串中的字符
操作
System.String类
Length(长度)、IndexOf(从左查找字符)、LastIndexOf(从右查找)、Insert(插入)、Remove(删除)、Replace(替换)、Split(切分字符串)、Substring(取子字符串)、Trim(压缩字符串的空白)、Format(格式化字符串)
System.Text.StringBuilder类
Length(长度)、Append(追加字符)、Insert(插入字符)、Remove(删除字符)、Replace(替换)、ToString(将StringBuilder转化为string字符串)
C#程序的流程控制
C#分支语句
if语句
如果双分支结构较简单,可以用条件运算符
多分支if...else if语句
switch语句
分支语句嵌套
C#循环语句
while语句
先判断表达式,后执行循环体
do...while语句
先执行循环体,然后判断循环条件是否成立
for语句
先赋值、再判断、执行、赋新值
foreach语句
foreach语句总是遍历整个集合,总是从集合中的第一个元素遍历到最后一个元素
如果循环体需要知道元素索引,那么必须使用for语句
foreach语句读出的元素变量是一个只读变量,不能对该变量进行修改,如果需要修改数组元素,那么必须使用for语句
循环语句嵌套
一个循环语句的内部可以包含另一个循环语句
循环嵌套时,要保证内层循环必须完全包含于外层循环之内
跳转语句
break语句
用于switch语句,表示跳转出switch语句
用于循环语句,表示提前终止循环,可与if语句配合使用
continue语句
只能用于循环结构,表示忽略continue后面的语句,直接进入本循环结构的下一次循环
while和do...whlie语句用于转去检测循环控制表达式
for语句用于转向表达式3以改变循环控制变量,再判定表达式2,以确定是否继续循环
面向对象程序设计入门
面向对象的基本概念
对象object
对象是构成系统的基本单位
任何一个对象都应该具有属性、行为这两个要素
对象=属性+行为(方法、操作)
事件Event与方法Method
事件又称消息Message,表示向对象发出的服务请求
方法表示对象能完成的服务或执行的操作功能
一个对象可以有多个方法,提供多种服务,完成多种操作功能,但这些方法只有在另外一个对象向该对象发出请求之后(发生事件)才会被执行
类Class与对象
类表示具有相同属性和行为的一组对象的集合,为该类的所有对象提供统一的抽象描述 (定义的形式相同不是指属性值相同)
类与对象的关系是抽象与具体的关系
抽象、封装、继承、多态
抽象abstraction
处理事物复杂性的方法,只关注与当前目标有关的方面,而忽略与当前目标无关的那些方面
类是对象的抽象,对象是类的特例
封装encapsulation
①将有关的数据和操作的代码封装在一个对象中,形成一个基本单位,各个对象之间相对独立,互不干扰。 ②将对象中某些部分对外隐藏,即隐藏其内部细节,只留下少量接口,以便与外界联系,接收外界的信息
封装的目的在于将对象的使用者与设计者分开,使用者不必了解对象行为的具体实现,只需要用设计者提供的消息接口来访问该对象
继承
不必再从头设计一个新类,只需要在A类的基础上增加一些新的内容即可。 若B类的对象拥有A类的所有属性和方法,即称B类对A类的继承
继承的优势在于降低了软件开发的复杂性和费用,使软件系统易于扩充,大大缩短软件开发周期,对于大型软件开发具有重要意义
多态polymorphism
多态性指在基类中定义的属性或方法被派生类继承后,可以具有不同的数据类型或表现出不同的行为。不同对象对统一消息会做出不同的响应。
为了实现多态性,需要在派生类中更改基类中自动继承来的数据类型或方法(称为覆盖)
多态的优势在于使软件开发更加方便,增加程序的可读性
类的定义
类的声明和实例化
类的声明
使用保留字class定义的数据类型称为自定义类(简称类)
类名是一个合法的C#标识符,推荐使用Pascal命名规范 Pascal命名规范要求名称的每个单次的首字母要大写
类的成员包括常量、字段、属性、索引器、方法、事件、构造函数
类的实例化
对象的声明与创建
声明 Book book1; //声明一个Book对象book1
这并不意味着在程序运行时该变量就获得了内存空间,为此,需要用“new”将其实例化
实例化 book1 = new Book(); //为book1分配内存空间
在声明的同时实例化 Book book2 = new Book(); //声明同时创建对象
类成员的访问
访问类成员时,一定要先实例化对象
类的内部访问 this.类成员
return string.Format("书名:{0}, 价格:{1}岁。", this.title, this.price };
类的外部访问 对象名.类成员
book1.title = "书名"; book1.price = 32; book1.GetMessage(); //调用对象的方法成员
类的数据成员和属性
常量
定义 public const float x0=0;
字段(类的成员变量)
字段不能使用var定义
public floaat r;
属性
public string Name //属性成员 { get { return name; //获取属性的代码 } set { name = value; //设置属性的代码 } }
public string Name; { get => name; set => name = value; }
若get访问器只包含return语句,set访问器仅仅简单使用value赋值,可用如下形式
类的可访问性
public公共成员
private私有成员
访问仅限于该类内部
internal内部成员
访问仅限于当前程序集
protected受保护的成员
访问仅限于该类及其派生类
protected internal
访问仅限于该类或当前程序集的派生类
①一个成员或类型只能有一个访问修饰符,protected internal除外 ②命名空间上不允许使用访问修饰符,命名空间没有访问限制 ③默认可访问性为private ④不嵌套在其他类型中的类型的可访问性只能是internal或public,默认internal
数据类型
值类型
包括 简单类型int、bool、char、float、double、decimal 结构类型struct 枚举类型enum
可以直接赋值和使用
引用类型
数组、字符串、类、接口、委托
在定义时不会分配空间,只是在实例化时才真正分配存储空间
装箱和拆箱
装箱
把值类型转换为对象的操作
装箱过程时隐式转换过程 int a = 56; object box = a;
C#中object类是所有类的最终基类
拆箱
把对象转换为兼容的值类型的操作
拆箱过程必须是显式转换过程 int a = 56; object box = a; int b = box; int c = (int)box; int d = (long)box;
类的方法
方法的声明和调用
方法的使用分声明和调用两个环节
声明
public int Add (int a, int b) { int x = a + b; return x; }
调用
同一类的内部调用 Add ( x, y )
在类的外部调用 cal.Add (x, y)
类的方法被调用时,可以作为 ①一条独立的语句 a.Answer(); ②表达式的一部分 String s = p.Answer(); ③另一个方法的参数 x =Convert.ToSingle(Console.ReadLine());
方法的参数传递
声明方法时,所定义的参数是形参(形式参数)
这些参数由调用方负责为其传递
调用方调用的是实际数据,称为实参(实际参数)
在调用方法时,参数传递就是将实参传递给形参的过程
值传递
引用传递
方法的重载
构造函数
面向对象的高级程序设计
静态成员与静态类
静态成员
通过static关键字标识,可以是静态方法、字段、属性或事件
与非静态成员的不同: 静态成员属于类而不属于类的实例 非静态成员总是与特定的实例(对象)相联系
当类的成员所引用或操作的信息是关于类而不是类的实例时,就应该设置为静态成员
注意: ①静态成员属于类,只能通过类名引用 ②静态数据成员在所有对象之外单独开辟空间,只要在类中定义了静态成员,即使不定义对象,也可以被引用 ③
静态构造函数
不是为了创建对象而设计的,而是用来初始化类 (只有非静态的构造函数采用来创建对象)
不能直接调用静态构造函数
静态构造函数可以与实例构造函数共存
类的构造函数也可以是静态的
静态类
静态类使用static关键字来声明
特点: 静态类仅包括静态成员 静态类不能被实例化 静态类是密封的 静态类不能包含实例构造函数
由于静态类是密封的,因此不可被继承
静态类不能包含实例构造函数,但仍可声明静态构造函数,以分配初始值或设置某个静态状态
类的继承性与多态性
类的继承性
优点
提高了代码的重用性
提高了程序设计的效率
提供了已有程序设计的可扩展性
派生类的声明
派生类可以拥有自己的成员,也可以隐式地从它地基类继承所有成员,包括方法、字段、属性和事件,但私有成员、构造函数和析构函数等除外
派生类的调用
派生类不能继承其基类的构造函数,但在构建对象时,会调用构造函数,并为对象分配内存并初始化对象的数据。 创建派生类对象时,为完成其基类部分的成员初始化,会调用基类的构造函数。 调用构造函数的顺序是先调用基类构造函数,再调用派生类的构造函数,以完成数据成员分配内存并进行初始化工作。
类的继承可以传递
密封类
为了阻止一个类的代码被其他类继承
添加关键词sealed可以声明密封类
类的多态性
使用new关键字重新定义类的成员
使用new关键字来定义与基类中同名的成员,即可替换基类的成员。
用virtual和override关键字定义类成员
抽象类与接口
嵌套类、分部类与命名空间
C#数据库编程技术
ADO.NET概述
使用ADO.NET访问数据库
LINQ to SQL编程