C#笔记
前六章:
2、掌握程序代码的结构
2.1 导入命名空间 语法:using System;
2.2 自定义命名空间 语法:namespace 自定义名称
2.3 自定义类名称 语法:class 自定义名称
2.4 程序入口函数(程序入口点)语法: static void Main(string[] args)
2.5 程序主体代码(需要程序执行功能)
高质量的编码准则
目的:提高代码的可读性、可靠性、可维护性、重用性、高效性。
布局这部分,VS这个牛X编辑器会帮你解决一部分问题
书写清晰:编写代码时尽量一行一行的写,就算是声明也最好独占一行
标识符规范:见名知意,主要使用在变量、函数(方法)、类型、接口、枚举、结构体、属性。。。
目的:当程序员阅读代码时能够从这些命名上知道这些对象在做什么事,这样一来就大大的节约时间,提高效率。
提示:如果名称太长则可以使用英文缩写,需要进行文档的记录。
良好的注释习惯:变量、函数、类、接口。。。。。当前的类中所有代码的简单说明
目的:提高阅读性
注释有三种:
1、单行注释://注释内容
2、多行注释:/*注释内容*/
3、块注释:
/// <summary>
/// 这里描述对象的功能
/// </summary>
/// <param name="args">对象使用时需要使用的参数</param>
===========================================================
数据类型
划分方法根据内存的存放位置进行划分
1、值类型 (保存在内存的“栈”中,特点:容量小、速度快、不灵活)
2、引用类型(保存在内存的“堆”中,特点:容量大、速度慢、很灵活)
值类型:
简单类型:其实就是数字类型(整数、小数)
枚举类型:其实就是给一些数字一个命名,方便调用,主要做标识。
结构类型:其实就是把一些内容合到一起然后给一个命名,和类一样但是它是存储在“栈”中。
引用类型:
类类型:其实就是把一些内容合到一起然后给一个命名,它是存储在“堆”中。
数组类型:其实就是一组同类型的数据给一个统一的名称。
接口类型:其实就是定义的一些规则,然后使用时必须遵守这些规则。
委托类型:其实就是将要做的事情交给其他对象去做,而不关心其他对象怎么做,只看结果。
什么是变量?
是内存中的一块存储空间,变量就是某块存储空间的一个名称。
变量名称其实就是指向内存的某块空间。
既然是空间那么就可以存放数据也就是所谓变量的值。
就相当于仓库,我们并不需要知道仓库在哪里,这件事情是底层的系统去做的,
变量<---也就是里面存放的内容是可以随时变化的。因此我们把它称为:“变量”。
变量是有数据类型,它的值也就是变量里面存放的数据一定是和变量的数据类型一致的。
变量是有作用范围的。
诀窍:就是看{}大括号的位置,只要在{}里面,就可以随意使用,超过了就不能使用。
{int x=0;{可以使用x,int y=10;}y=20;<--这个地方不能使用y变量}这种包含只能是单向的,也就是说内部的{}可以使用外部{}中的变量,反之不行
声明变量时一定要有数据类型,因为如果没有数据类型那么编译器将无法分配内存空间。
变量声明后如果没有初始化(第一次赋值)是不能使用的,此时如果使用就会导致编译器的错误:使用了未赋值的变量,(这里是指对未赋值的变量进行取值操作)
变量使用的诀窍:先赋值再使用。
所谓的访问变量其实就是对变量进行取值或重新赋值的操作(读/取)
声明变量:就是指定变量的名称和数据类型
语法:
数据类型 空格 变量名称 空格 分号结束
int age ;
初始化变量:
age = 18 ;(就是第一次给变量赋值)
可以一次声明多个同类型的变量每个变量用逗号隔开
例如:int length,width,height;
int length=10,width=30,hight=20;(声明并直接初始化变量)
---------------------------------
C#中控制台输入使用的是ReadLine()函数,这个函数属于Console这个类里面的。
ReadLine()函数作用:
接收用户通过键盘向控制台输入字符,回车表示用户输入完毕,ReadLine()函数将用户输入的字符串返回到程序中供后台程序处理。
程序运行时如果执行到ReadLine()函数则程序暂停并等待用户的输入,直到遇见回车后程序才继续执行,当程序需要进行调试时可以将ReadLine()函数放在程序的最后执行,这样就可以看到前面程序运行的结果了,否则调试程序将直接运行到结束。
由于ReadLine()返回的都是字符串因此如果使用的数据类型不是字符串则需要进行数据类型的转换,否则就会出错这种错误就是“语义错误”,转换有可能会失败。
---------------------------------
常用的转换语法:
数据类型.Parse(字符串)
int.Parse("18");
double.Parse("23.3");
long.Parse("99999999");
DateTime.Parse("2020-03-19");
控制台输入转换的语法:
//除了字符串以外都需要进行数据类型转换
数据类型 变量 = 数据类型.Parse(Console.ReadLine());
---------------------------
常量就是不变的数据,
三种常量:
字符常量、符号常量、枚举
使用最多的就是符号常量,
常量的特点:
一旦声明就必须赋值一旦赋值就不能更改
const int tag=20;<---常量,常量的关键字是const
--------------------------------
什么是变量?
变量就是内存中的一块空间,用于存放数据。
相当于数学中的X。
变量本身只是这个内存空间的一个指向(名称)
------------------
为什么说变量是有类型的?
因为前面我们学习过数据类型,因为我们人类擅长分类,通过这点学习进步并且将知识流传下去。兔子和老鼠都是属于啮齿类,熊和狗都是属于犬科。
------------------------------
使用变量的步骤:
1,定义变量
1.1 声明变量(开辟内存空间)
1.2 初始化变量(为变量第一次赋值,变量如果没有赋初值是不能使用的)
2,存取数据
-----------------------
语法说明
int age;age = 18;
前面的int代表数据类型是整形,空格后面的age代表变量名称,分号代表语句结束。声明时数据类型和变量名之间的空格是用来给编译器识别前后的
age = 18;
前面的age代表变量名称,等号代表赋值,18代表具体的数据/同类型变量
-------
小技巧:
使用#region 和 #endregion对之间包裹的代码进行折叠,以获取更大的编写空间
=============================
变量命名的规则:
见名之意(见到变量名称就可以知道变量的含义)
有标识的意义,不做无意义的变量名称
---------------------------
控制台的输入是使用
Console.ReadLine();这个函数完成,它主要是接收用户在控制台的输入,但是用户控制台的输入全部都是字符串,不管用户是输入的数字还是字符,对它来说都是字符串。
当用户输入完成时只有按下回车键才会将输入的信息返回到程序中
======================================
由于之前的代码较多所以新建一个启动类用于编写新的代码
但是新类中也有程序入口函数所以必须要进行选择,启动哪个Main函数
设置的位置在解决方案资源管理器中->右键点击项目->选择属性->弹出的面板中选择启动函数
案例:输入学生的信息
string name;char sex;DateTime birth;int cellphone,qq;string email;
输入时需要给用户提示
输出的占位符索引是从0开始的(PS:C#中只要是索引都是从0开始)
--------------------
bug:手机号码使用32位整型数据导致长度不够的异常,
解决方法:
1,修改数据类型为long长整型
2,修改数据类型为字符串
大家的选择是2-->long,你自己做的时候也可以使用字符串
--------------------------
什么是常量?
简单的说就是不可变的标识
例如:数字32是不能变的,因为变了就不是数字32了,因此数字32就是一个常量。
符号常量:
例如:const int x=12;表示这个x是一个常量,不能更改。
所以声明变量时前面加上const关键字就表示该变量是一个常量
常量语法:
const 数据类型 常量名称 = 值;
常量规则:
一旦声明必须赋值一旦赋值不能更改
-------------------
变量和常量使用时机
如果程序中数据需要经常改变则使用变量,如果是不变的数据,例如:圆周率PI,重力加速度G等这些都是不变的,所以使用常量做标识。
--------------------------------
程序的错误:
语法错误、语义错误
语法错误编辑器可以直接指出
语义错误需要程序员自己查找并修改。
调试的步骤:
1、设置断点(快捷键:F9)
2、启动调试(快捷键:F5)
3、单步执行/逐步运行(快捷键:F11)/逐过程运行(快捷键:F10)
4、观察变量的值的变化,从而发现问题,同时也可以借助调试理解程序的运行
5、中断或停止调试(目的是查看并修改代码)
6、修改代码
诀窍:在合适的地方设置断点,能够极大的节约时间。提高效率。
7、重新调试(重复上面的步骤直到所有错误消除)
------------------------------------------------
运算符分类;
1、根据操作数可以分为:一元运算符、二元运算符、三元运算符
2、根据运算类型可以分为:算术运算符、赋值运算符、自运算符、关系运算符、逻辑运算符、条件运算符
第七章:类型转换
数字和数字字符串
数字:1,12,18,20<-----这些都是数字
数字字符串:"12","30","32"<-----这些都是数字字符串
它们的区别在于计算机中的编码不同
由于编码不同所以呢 1="1"<---这个等式是不成立的,当然这里的=号也就是赋值运算符,右边的赋给左边。
int x =2/0.3<----参与运算的操作数类型不同,因此这个表达式是错误,要想这个表达式成立就必须进行类型的转换。
C#中两种类型转换:隐式、显式
隐式:就是一般直接转,不用明显看到就可以成功。
显式:就是明显看出是在做类型转换
------
隐式转换示例:double x;int y=10; x=y;<-----这个表达式是成立的,因为x是浮点,y是整数,而浮点大于整数因此这就发生了隐式转换
-------------
显示转换示例:double x=2.8;int y;y=x;<----此时表达式不成立,要想表达式成功则需要这样写:y=(int)x; <--这样明确指定目标类型(被赋值对象的类型),注意此时不会产生四舍五入,而是直接砍掉小数点后面的
显示转换回导致精度的丢失。有可能发生System.OverflowException<---溢出异常(超过目标类型的容量范围)
float i = 18.89f ; int j = 3; double m = 5;
j = i + j+m;<---正确的表达式:j = (int)i + j + (int)m;
这就是一种显示转换的方法:(目标类型)变量,
语法示例:int i=0;float j=1.8f;i = (int)j;
第二种:目标值类型.Parse(string类型变量)<---仅对数字字符串有效
使用这种显示转换的方法一般会出现的错误是:System.FormatException 输入字符串格式不正确的错误
这种转换字符串表示的值一定要在目标值类型的范围以内,超过就会出错误。
第三种:ToString()转换
语法:目标变量.ToString();
示例:int x=13;x.ToString();
注意:变量在没有明确赋值时,变量的值是不会改变的。
明确赋值有哪些---->例如:x++(明确赋值),x--(明确赋值),x+=2(明确赋值),x=13(明确赋值)
第四种:Convert.To目标类型 转换
Convert是一个类,它下面有很多转换的函数,也就是说这个类就是用于类型转换的。使用以To开头的函数进行类型转换
例如:
Convert.ToInt32(数据)<---转为32位的整数
Convert.ToInt64()\.ToInt16...
Convert.ToDouble().....
可以在编辑器中使用点运算符进行查看。
示例:字符串“12345”转为整数12345
Convert.ToInt32("12345");
注意:使用Convert.ToInt32时会发生四舍五入的情况
===============================================
注意:
类型转换特别是显示转换时,一般出现语法错误的情况比较少而出现语义错误的情况比较多,因此进行运算时如果参与运算的数据类型不一样结果要以精度大,范围大的为准。
以后可以通过类型的判断来防止出现上述的错误。
还可以通过限制外部的数据输入来进行控制防止出现错误。
第八章复习:
vs中的解决方案资源管理器作用:
管理项目和解决方案,
项目中可以管理的包括有:
1、项目文件
1.1 项目的属性
1.2 项目所在的路径
1.3 添加项目以及各种内容
1.4 设为启动项目
1.5 生成项目,重新生成项目
1.6 移除项目和重命名项目
2、项目属性的管理(程序集的管理)
3、引用的管理(*.dll,*.ocx...库的管理)
4、代码源文件(*.cs)
-----------------------------------
一个C#程序的基本结构:
1、导入命名空间
2、自定义命名空间
2.1 自定义类
2.1.1 函数(主函数和其他函数以及其他的对象)
所以一个C#的结构实际是两层结构:
第一层是导入需要的库
第二层是需要编写的内容
其中第二层是一种包含关系:
自定义命名空间包含自定义类
自定义类包含函数和其他对象
第二层的组织方式使用{}括号进行组织和区分相互的边界,
{}括号边界的特点:
由内可以访问到外部的对象(函数、变量、属性、其他的对象)
由外是不能访问内部的对象
--------------------------------------------
由内访问外部的路线:函数---》类---》空间
---------------------------------------------
每一条语句的结束都要用英文的分号表示
注释有三种:单行注释、多行注释、块注释
//--->这是单行注释
/*
---->这是多行注释
*/
///
/// --->这是块注释
///
------------------------------
标点符号在C#中都是以英文的为主,不能使用中文的标点符号,因为编译器无法识别中文的标点符号
----------------------------
C#中的括号有三种:小括号()、中括号[]、大括号{}
--------------------------
C#中的关键字:
https://wenku.baidu.com/view/6e5291fd814d2b160b4e767f5acfa1c7ab00824d.html
关键字一般以蓝色标识,是程序内部的语法成分,是由编译器使用的,一般不能将关键字作为变量、函数、类。。。
----------------------------
第九章复习:
C#中的标识符
标识符是用来识别类、变量、函数或任何其它用户定义的项目。(通俗的说就是类名、变量名、函数名等)在 C# 中,类的命名必须遵循如下基本规则:
标识符必须以字母、下划线或 @ 开头,后面可以跟一系列的字母、数字( 0 - 9 )、下划线( _ )、@。
标识符中的第一个字符不能是数字。
标识符必须不包含任何嵌入的空格或符号,比如 ? - +! # % ^ & * ( ) [ ] { } . ; : " ' / \。
标识符不能是 C# 关键字。除非它们有一个 @ 前缀。 例如,@if 是有效的标识符,但 if 不是,因为 if 是关键字。
标识符必须区分大小写。大写字母和小写字母被认为是不同的字母。
不能与C#的类库名称相同。
来源:https://www.cnblogs.com/wodewei/p/11493238.html
==================================================
C#控制台的输入输出函数:
Console.WriteLine();//<-----输出小括号中的内容并换行
Console.Write();//<-----输入小括号中的内容不换行
------------
Console.ReadLine();//<----接收控制台键盘的输入并返回到程序中
Console.Read();//接收控制台键盘输入的第一个字符对应的ASCII编码值
Console.ReadKey();//获取用户按下的下一个字符或功能键,按下的键显示在控制台窗口中
===============================
数据类型:
最高类型是object
根据内存中存储位置可分为:值类型、引用类型
值类型:存储简单数据,高效率,低灵活
引用类型:存储复杂数据、低效率、高灵活
==========================
变量:
变量代表一块内存空间,变量名就是这块内存空间的临时名称。
变量是由数据类型、变量名、变量的值组成
变量必须先赋值后使用。
变量的使用分为:取值、赋值
变量可以重复使用,变量的作用范围主要是看声明在那个{}里面
================
常量:
对于变量来说是不变的量,
特点:一旦声明,必须赋值,一旦赋值,不能更改。
三种常量:
字符常量、符号常量、枚举
常量声明时必须加上const 作为标识后面和变量一样
第十章:结构化程序设计
使用结构化程序设计可以编写结构清晰,可读性强,容易排错等优点所以使得程序设计的效率和质量都有得到更好提高。
三种结构:
1、顺序结构:
特点根据书写的顺序自上而下的执行
2、选择结构
特点根据条件进行判断从而选择判断结果为真语句执行
3、
循环结构
特点根据条件判断如果为真则不断的反复执行某段语句直到条件为假终止循环
流程控制语句有三种:
1、选择语句
2、循环语句
3、跳转语句
三种语句帮助实现三种结构。
------------------------
使用if语句实现选择结构
if语句四种形式:
1、单分支if语句(只有一个分支的)
2、双分支if语句(有两个分支供你选---》成立/不成立)
3、多分支if语句(有更多(两个以上)分支供你选择,但是只能多选一)
4、嵌套if语句(层层递进的选择)
--------------------
单分支if语句
语法:
if(布尔表达式)
{
布尔表达式结果为真时执行的语句块
}
======================================
双分支if语句
语法:
if(布尔表达式)
{
布尔表达式结果为真时执行的语句块
}else
{
布尔表达式结果为假时执行的语句块
}
============================================
多分支if语句
语法:
if(布尔表达式)
{
布尔表达式结果为真时执行的语句块
}else if(布尔表达式)
{
布尔表达式结果为真时执行的语句块
}......
else//并不是必须的
{
布尔表达式结果为假时执行的语句块
}
十一章:嵌套if语句
嵌套:就是一层里面还有一层。
if语句中间可以包含n个if语句这种情况就称为:“嵌套”
嵌套if语句执行的流程:
先执行外层的if如果成立则执行内层的if语句。如果里面还包含if语句则还是这样执行。
PS:一个if语句只能对应一个else语句,而且只和最近的else语句匹配。所以在写if语句时一定要注意括号,否则当if语句较多时很容易出现匹配不当的情况,这种情况不属于语法错误,属于语义错误。
小窍门:书写if语句时当if后面的布尔表达式写完后立即回车换行然后打上一对大括号,然后光标回去一格然后回车。如果发现括号不匹配了,那么请首先找到左边的折叠标识进行折叠,这样能够帮助我们快速的找到括号不匹配的问题。
-----------------------------------------
嵌套if语句是当需要层层递进的判断时就使用if语句的嵌套
-----------------------------------
注意这里的并不是绝对的:
当出现嵌套if语句的逻辑时如果可以更加清晰话那么就改为多分支if语句
如果多分支if语句逻辑更加模糊的话那么就使用嵌套。
这样的事情称为:“代码优化”
十二章:switch语句
1、什么是switch?
switch语句可以判断很多条件,适合从一组互斥的分支中选择一个分支执行。
语法说明
switch语句后面的表达式必须是一个变量
case 后面必须是常量,它的类型一定和switch表达式的类型一致。
default语句是可以省略的,如果有那么就只能有一个。
switch表达式的数据类型只能是:整数,字符,字符串,布尔,枚举
-----------------------------------------
switch语句的贯穿用法:
多个条件不同,但是执行一样这种情况下我们就可以使用switch的“贯穿”
虽然使用if也可以做到但是如果要判断的条件仅仅是等于关系那么使用switch会更加清晰容易阅读
条件虽然不同判断是一样都是等于而且执行也是一样的那么就可以使用switch
========================================
多分支if语句与switch语句相同点:
1、都能实现多分支选择
2、多分支if语句和switch语句都能实现不需要层层递进判断的多分支
多分支if语句与switch语句不同点:
1、嵌套语句语法复杂、有代码冗余、结构容易混乱,但是层层递进逐步判断只能使用嵌套
2、switch语句语法简洁,但是只能判断相等关系,不能判断区间。
3、除了层层递进和相等关系就选择多分支if语句
=======================
注意:
switch语句中每个case后面的常量值必须唯一,否则语法错误
case后面必须跟上break退出case,如果不写就会出语法错误
使用贯穿case时在最后一个case后面写上break退出否则语法错误
default语句是可以省略的,如果有那么就只能有一个。
十三章:循环语句
程序的三种结构:
1、顺序
2、选择(判断)
3、循环
-----------------------------------------
什么是循环?
1、不断的重复进行--》循环
2、直到某条件不成立终止循环---》循环结束
3、如果条件永远成立则为“死循环”
----------------
两种情况:
1、先判断再执行(循环)
2、先执行一次再判断,条件为真则继续执行直到条件为假退出循环
---------------
C#中的四种循环语句
1、while(循环)
2、do...while(循环)
3、for(循环)
4、foreach(循环)
-------------------------
while循环是一种当型循环,就是当条件满足为真时执行循环,当条件不满足为假时退出循环。
while(布尔表达式)
{
//循环体语句
}<----不用写分号结束
----------------------------
循环的核心是控制循环的次数,所以一般使用整数进行控制,例如:int i;
循环的三要素:
1、初始部分:从哪里开始
2、终止条件:到哪儿结束
3、迭代部分:循环语句体的执行
-----------------------------
while循环语句其实最适合做次数不确定的循环,
但是却知道什么条件才终止循环的场景。
-----------------------------------
while中表达式可以逆向判断,也就是说可以进行取反的判断,使用关系运算符中的(!=)不等于运算可以进行取反的操作。
---------------------
除非我们有意引入死循环,否则一定要在程序中避免死循环。
-----------------------
do...while循环是先执行一次循环体语句然后在判断循环条件是否为真。
使用场景:
当需要无论什么情况都要先执行语句然后在确定是否循环的情况下,使用do...while循环会更适合。
------------------------
语法:
do{
//循环体语句
}while(布尔表达式); <---这里一定不要忘记了分号结束语句
---------------------
do...while循环至少会执行一次。while循环可能一次都不执行
while是先判断再执行,do...while是先执行一次或多次再判断是否循环
--------------------
死循环产生的必要条件:就是循环终止条件永不为假。
十四章:for语句
回顾
while和do...while区别?
1,while是先判断后执行,有可能一次都不循环
2,do...while是先执行一次循环,然后在判断是否执行循环,所以无论如何都会执行至少一次。
3,while和do...while都适合于不知道循环次数的循环
----------------------------------------
for语句?
for循环语句也叫“迭代语句”
名词解释:迭代
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
重复执行一系列运算步骤,从前面的量依次求出后面的量的过程。此过程的每一次结果,都是由对前一次所得结果施行相同的运算步骤得到的。例如利用迭代法*求某一数学问题的解。
对计算机特定程序中需要反复执行的子程序*(一组指令),进行一次重复,即重复执行程序中的循环,直到满足某条件为止,亦称为迭代。
--------------------------------
for语句也称为:计数器循环语句
for语法:
for(表达式1;表达式2;表达式3)
{
循环语句
}
-----------------------
在同一个作用范围内不能声明相同变量名的变量,因为这样会产生二义性。编译器将不能识别。
------------------------------
for语句中三个表达式的作用:
表达式1作用是赋初值,仅在开始执行一次
表达式2每次都会执行,用于判断是否终止循环
表达式3作用是对表达式1的变量进行累加或递减,第一次不会执行,以后每次都会执行直到循环终止
----------------------------------
for可以有四种表现形式
1,for (i = 1; i <= max; i++) <---基本用法
2,int i=0;
for (; i <= max; i++) <---第二种
3, for (i = 1; i <= max; ){i++;} <---第三种
4,for (i = 1; ; i++) <---第四种
{
if (i <= max)
{ //语句}
else{break;}
}
-------------------------------
while、do...while、for相同点
1、都是循环语句,有固定的语法
2、都是有循环条件和循环体构成
3、循环的核心都是控制好循环的次数,次数又由三点决定:
a、初始部分
b、终止条件
c、迭代部分
------------------------------
while、do...while、for不同点
1、while、do...while适合用于循环次数未知的情况,for循环适合循环次数确定的情况
2、while、do...while初始部分通常在开始之前就完成了,for循环则是在语法表达式的表达式1部分完成
3、while、do...while循环的迭代是在循环体中完成,for循环是在语法结构的表达式3部分完成,for循环是将三要素同时写在for后面的小括号中
4、while和for是先判断在执行,如果条件一开始就不成立,则循环一次都不执行。do...while先执行在判断,无论条件是否成立最少执行一次。
-----------------------
注意:
for语句中三个表达式,如果为空也必须使用;号进行站位。如果缺失则语法错误
十五章:跳转语句
跳转语句
通俗的说就是从一个地方跳到另一个地方。
是属于流程控制语句中的一种,用于无条件的转移控制
C#中提供了四种跳转语句
1、continue:立即终止当前这一次循环,进入下一次循环。(仅用于各种循环语句,只能作用于包裹它的循环)
2、break:立即终止当前循环或退出switch语句(仅用于各种循环语句和switch语句,只能作用于包裹它的循环或switch)
3、goto:无条件跳转,可以跳转到任意指定标签位置。(可以构成循环效果)现代编程中是严禁使用
使用goto语句的地方一般是在受限设备中,例如:各种芯片中使用,因为芯片中的空间有限通常只有几k或几十k的空间
4、return:立即跳出当前(包裹return)函数,不会执行return后面的语句,函数也会立即终止执行。
return语句也是用于终止函数执行的语句
-----------------------------------------
continue、break、return这三个跳转语句后面的代码是不会执行的,因为这三条语句已经跳转到别处,所以后面的代码等同于失效代码,因此也会称为:检测到无法访问到的代码
-----------------------------
跳转语句用于无条件的转移控制。
十六章:数组
什么是数组?
数组是一种结构,是把相同类型的数据按有序的形式组织起来。
通俗的理解:
以苹果举例:
每个苹果都看成一个具体数据,以前是用小盒子(变量)存放,当大量使用时就会不方便,所以如果将要使用苹果全部放到某一个空间中,那么效果就会很好。
这种情况下使用数组进行存放同一种类型的数据就会非常方便。
C#中数组可以分为:
一维数组、多维数组、数组的数组
-----------------------------
数组的使用步骤:
1、声明数组(数组的类型和数组的名称)
2、创建数组(请求内存空间的分配)
3、初始化数组(给数组中每个空间放一个值)
一维数组的语法:
数据类型[] 数组名称;<-----声明一个数组对象
例如:int[] ages;//声明一组年龄的数组用于存储年龄的值
声明数组时要注意的事情
1、数据类型是C#语言中的任意数据类型
2、数组名称必须满足标识符的命名规范和变量的命名规范是相同的
数组名称 = new 数据类型[数组的长度];<----申请空间,包含多少个同类型的空间(数组长度)
ages = new int[10];<---创建整型数组对象,申请空间用于存放10个整型数据值
创建数组时要注意的事情
1、创建数组时,数组的长度不能省略,长度可以是常量、变量或表达式
2、数组的声明和创建可以合并到一起的。例如:int[] ages = new int[5];//这种写法比较常见
初始化数组
数组名称[索引] = 值;<---为数组的某个空间赋初值
int[] ages = new int[5];//声明并创建一个整型数组
ages[0] = 18;//将18 赋值给ages数组的第0个空间中
ages[1] = 20;//将20 赋值给ages数组的第1个空间中
ages[2] = 13;ages[3] = 22;ages[4] = 19;
------------------------------------------------
ages[5] = 10;//这句赋值的代码是错误的。因为ages数组只有5个空间,空间的索引值从0开始
------------------------------------------------
数组的索引从0开始因此数组的索引值一定是小于数组的长度,小一个
==============================================
一维数组的动态初始化
语法:
数据类型[] 数组名称 = new 数据类型[]{值1,值2,值3,值4,....值N};
动态初始化时数组会根据初始化值的个数来确定数组的长度。
例如:
int[] ages = new int[]{12,13,23,22,18,16};
一维数组静态初始化
语法:
数据类型[] 数组名称 = {值1,值2,值3,值4,....值N};
例如:
int[] ages = {13,15,16,8,19};
===========================
元素的默认值:
数组是一种对象类型(属于引用类型),一旦创建对象则系统默认会给出原始初始化值。
int 类型 默认值 0
float 类型 默认值 0.0f
bool 类型 默认值 false
char 类型 默认值 '\u000'(表示一个空字符)
string 类型 默认值 null(对象的默认值就是null)
================================
一维数组的访问:
数组名[索引] = 值;//为数组的指定索引的元素赋值
数组名[索引];//获取数组中指定索引的元素值
例如:
int[] ages = new int[5];
赋值:
ages[0] = 20;
取值:
int age = ages[0];//将指定索引位置的元素值取出赋给同类型的变量
=====================
数组和变量不同
数组的初始化其实是第二次赋值,变量的初始化才是真的第一次赋值
=======================
注意:
数组的长度是固定的,在C#语言中数组的长度一旦确定是不能更改的。
数组的索引一定小于数组的长度,否则会出现“索引超出了数组界限。”错误
十七章:数组的遍历和二维数组
一维数组的遍历
遍历:就是将集合内容进行逐个的访问。(例如:课堂上的点名)
是利用循环进行的,是通过数组的索引值进行计数循环,从而达到遍历数组元素的目的。
使用for这种循环进行数组的遍历。
由于for本身是一种计数器循环所以很容易的就和数组的索引值结合,这是天然的结合。通过这种结合就可以轻松的遍历数组中的每一个元素。
for循环遍历一维数组的语法:
for(数据类型 循环变量=0;循环变量 < 数组名.Length;循环变量++){操作数组元素;}
Length:<---长度(数组中表示包含元素的个数)
int[] ages = new int[5];
此时数组的长度就是5,也就是说ages数组中可以存放5个整数。那么ages.Length就是得到ages数组的长度
------------------------
除了for循环经常用于集合的遍历外,C#还提供了foreach这种针对集合遍历的语句,方便我们对各种集合进行遍历
语法:
foreach(数据类型 循环变量 in 数组名称){语句块;}
------------------------------
一维数组的遍历
可以使用循环语句进行,但是前三种循环只能使用索引进行,foreach是专门针对集合进行遍历的结构,
foreach每次只能遍历一种数据类型的集合,其他三种遍历时只和索引有关和数组类型无关,如果数组的长度是一样则可以使用前三种循环语句结构,进行一次性同长度,不同类型的数组同时遍历。
----------------------------------
二维数组
也是数组的一种,它是一组连续的内存空间,但是方向分为横向和纵向。
因此我们常常把二维数组看成一张二维表格
-----------------------------
二维数组的声明和创建以及初始化
语法:
1、声明
数据类型[,] 数组名;//<---中(方)括号中的逗号将数组标识为二维数组。
2、创建
数组名 = new 数据类型[长度1,长度2];//<---长度一代表行的数量,长度2代表列的数量
//同时,长度1也表示二维数组中第一维的长度,长度2也表示二维数组中第二维的长度。
3、声明和创建二合一
数据类型[,] 数组名 = new 数据类型[长度1,长度2];
4、初始化二维数组
4.1 string[,] users = new string[2,2];
user[0,0] = "jack";<---第0行,第0列
user[0,1] = "sunny";<---第0行,第1列
user[1,0] = "Jhon";<---第1行,第0列
user[1,1] = "Tom";<---第1行,第1列
每个二维数组都有两个下标(索引),分别是行下标和列下标
4.2 stirng[,] = new string[,]{{"tom","rose"},{"jack","sunny"},{"mike","nancy"}};//动态初始化
这个相当于3行2列的二维数组;--->string[,] users = new string[3,2];
4.3 stirng[,] = {{"tom","rose"},{"jack","sunny"},{"mike","nancy"}};//静态初始化
--------------------------
二维数组的遍历
1、使用集合访问迭代器foreach
语法:
foreach(数据类型 循环变量 in 二维数组名 ){循环体语句;}
使用foreach循环二维数组时是不考虑数组元素的索引,它会将数组中元素从头到尾全部提取出来。
2、使用for循环遍历二维数组
二维数组有两个维度:行维度和列维度
也就是有两个索引:行索引和列索引
需要取出二维数组每一个维度的长度
数组名.GetLength(维度索引)//获取指定维度的长度
C#语言中涉及到索引则都是从0开始
如果是第一维则维度索引就不是1而是0,第二维的维度索引就不是2而是1,因为索引是从0开始
使用数组名.Rank属性得到数组的维度
十八章:排序
1、什么是排序?
就是将杂乱无章的数据按照某种格式进行排列的一种方式。
排序的目的是为了更好的、更快的搜索和查找数据。
2、排序的算法
就是怎样高效排列数据一种计算方法。
3、排序算法种类
3.1 冒泡排序
3.2 插入排序
3.3 选择排序
3.4 快速排序
4、冒泡排序的算法
反复对两个元素进行比较,如果这两个元素的顺序错误则进行交换。
原理:
1、比较相邻的元素,如果第一个比第二个大则交换它们两个
2、对每一对相邻的元素做同样的工作,从开始的一对到结尾的最后一对
3、针对所有的元素做同样的步骤,除了最后一个
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较了。
原理分析:
设待排序的数组a中有n个元素,冒泡排序要进行n-1趟,每趟循环均是从比较相邻的两个元素开始,一直到最后两个元素。
算符实现的描述
两个循环进行嵌套
外循环和内循环均是循环这个数组a。
int[] a = {6,2,4,1,5,9}
外循环
for 从0-5六个元素,索引为i
内循环
fro 从0-5六个元素,索引为j
外循环第一次
i=0,进入内循环j=0,内循环第一次
a[i]>a[j+1]true
a[i]=a[j+1];<---交换两个元素的位置
内循环第二次
a[i+1]>a[j+1]true
a[i+1]=a[j+1];<---交换两个元素的位置
==========================
选择排序算法
算法原理:
1、从待排序的数组元素中选择值最小的或值最大的元素并将它与第一个元素进行交换
2、然后从不包括第一个位置的数组元素中选择最小的或最大的元素并将它与数组中第二个元素交换位置
3、重复前面的操作直到剩下一个元素为止。
===========================================
冒泡排序:
很简单的一种经典排序算法。
但是普通情况下会有空循环的情况。
6个元素的数组来说
内循环会空跑12趟左右,外循环会空跑2趟左右
长度为6的数组,外循环每循环一次,内循环会循环6次
内外循环一共要循环6*6=36次。
=================================
当你从百度上找到你想要的代码时,不要马上拷贝到你的vs中执行。
而是要先观察理解代码的含义(思路),然后将代码复制到vs中,但是不要马上运行,事先需要整理代码。
当把代码整理好了后,再去运行。
因此就需要优化代码,提升效率。
=================================
插入排序
算法原理:
1、顺序的将待排序的元素按值的大小插入到已排序的元素子序列的适当位置
2、子序列的元素个数从1开始逐渐增大,当子序列的元素个数和数组中的元素个数相同时排序完成
十九章:复习指导-程序的结构
程序的三种:
一、顺序结构
二、选择结构
三、循环结构
这三种结构能够解决目前已知任何问题。
这三种结构的出现是通过研究人类行为得出的结论。
顺序结构(一个人的一生)
可以称为:开弓没有回头箭。
人一旦出生则终点以现。放在程序中就是一个大的顺序结构。
例如:操作系统,你一开机就意味着一段时间的开始。如果你一关机,就表示系统重新再来一次。
大的顺序结构。
放到自己的程序中则是从程序开始执行到程序结束,就是一个大的顺序结构。
就是从Main函数执行开始到执行结束。
选择结构
依托于顺序结构不能单独存在。
以人来说,每天每时每刻你都要做出无数种选择。这些选择会改变非常小的流程
选择结构改变流程是指内部小的流程而不是整体大流程。
C#程序中选择结构帮助我们对内部的执行流程做出一定的改变。
C#为了达到改变内部小流程的目的,创造了if语句和switch语句来达到目标
if语句是C#提供的选择结构的操作语句
if语句的四种形势:
1;单分支结构
2;双分支结构
3;多分支结构
4;嵌套结构
语法:
1,单分支
if(bool表达式)
{
//表达式结果为真时要执行语句
}
2,双分支
if(bool 表达式)
{
//表达式结果为真时要执行语句
}else
{
//表达式结果为假是要执行语句
}
3,多分支
if(bool 表达式)
{
//表达式结果为真时要执行语句
}else if(bool 表达式)
{
//表达式结果为真时要执行语句
}。。。。。。
else
{
//表达式结果为假是要执行语句,这个else语句并不是必须的
}
4,嵌套
if(bool 表达式)
{
//表达式结果为真时要执行语句
if(bool 表达式)
{
//表达式结果为真时要执行语句
}
}else
{
//表达式结果为假是要执行语句
if(bool 表达式)
{
//表达式结果为真时要执行语句
}
}
-----------------------
以上就是if语句的四种结构形势。
如何选择中间的哪一种呢?
如果你只需要做一个判断,但是后面任然是继续执行并不影响其他,那么使用单分支即可。
如果你需要无论判断成立还是不成立都要做不同的事情,那么使用双分支即可
如果你需要在多种情况下选一个执行,那么使用多分支即可。
如果你需要层层递进的判断,那么使用嵌套即可
----------------------------------------------------
多分支语句的简洁形势:
switch语句
语法:
switch(表达式)
{
case 常量表达式:
break;
case 常量表达式:
break;
......
default:语句块;
break;
}
同样实现多分支语句的功能,但是switch只能进行相等的比较,不能进行范围比较,而且case后面只能是常量表达式。switch还有一个高级用法就是“贯穿”,
贯穿用法:几种情况不同但是处理方式是相同的,此时可以使用“贯穿”
switch(表达式)
{
case 常量表达式:
case 常量表达式:
case 常量表达式:
case 常量表达式:
break;
case 常量表达式:
break;
......
default:语句块;
break;
}
switch语句结构不能完全取代if多分支,因为switch不能判断复杂的条件,只能判断相等的关系。
-----------------------------------------------------------------------------------------
循环结构
C#中提供了四种循环语句来实现循环的功能。
while 循环
do...while 循环
for 循环
foreach 循环
---------------------------
while循环语句
是用来针对于不知道循环次数但是知道终止条件的情况下使用的一种很方便的语句。
while语句的特点是开始进行是否循环的判断,因此while循环可能出现一次都不循环的情况。
语法:
while(bool表达式)
{
//循环语句块,循环体
}
---------------------------------
do...while循环语句
和while循环是差不多的,但是它的特点是无论如何都会先执行一次循环然后再去判断是否继续循环。
语法:
do
{
//循环语句,循环体
}while(bool表达式);//<-----就这一个循环需要分号结束
---------------------------------------------
跳转语句:
C#中提供了四种跳转语句
1、goto语句
2、break语句
3、continue语句
4、return语句
-------------------
goto语句是和标签一起使用,用于改变程序执行流程,
程序在执行过程中一旦遇到goto语句则会立刻跳转到goto语句后面指定的标签处。执行标签后面的语句。
语法:
标签名://<---标签一般独占一行
代码行//<---跳转后要执行的代码
goto 标签名处;//<---goto 到指定的标签
例如:
label1:
Console.WriteLine("goto跳转到这里");
goto label1;
以上的示例可以形成死循环。
goto语句由于是无条件跳转所以容易照成代码结构的混乱不易阅读,因此在应用层开发中一般禁止使用goto语句。但是在底层开发受到设备的限制所以使用goto会更加方便。
-------------------
break语句主要使用在两个地方
1、switch语句中用于结束case语句
2、循环语句中用于终止break语句所在的循环
----------------------------------------
continue语句主要用于循环中
作用:结束本次循环直接进入下次循环,可以加速循环。
循环中一旦遇到continue语句则后面的语句将不再执行而立刻从头再次执行循环
=============================
综合提升---猜数字小游戏
用户输入时可能不会正确输入数字,因此程序中需要进行处理。
--------------------------------
游戏中处理用户数字输入不正确的方法:
使用 类型.TryParse 函数对用户输入的内容进行判断,如果转换成功则返回真,否则返回假。
由于是循环嵌套因此,内层循环的break语句不能退出外层,所以可以先在外层循环中增加一个bool的变量作为判断的依据,
//声明一个用户输入是否正确的变量
bool isNumber = true;//默认为真(相信玩家是正确输入的)
一旦发现玩家输入不是数字则停止当前的游戏,返回到开始,让玩家重新再来一次。
-------------------
增加游戏的背景音乐
1、导入命名空间(using System.Media;)
2、找到wav格式的音乐,存放到和exe相同的目录
3、定义SoundPlayer对象 sp
4、使用sp播放指定的音乐
二十章:复习for语句
for循环语句
又称为计数器循环,它主要用于知道循环次数的循环。
语法:
for(表达式1;表达式2;表达式3)
{
//循环体语句
}
for(int i=0;i<count;i++)
{
//循环体语句
}
表达式1用于定义并初始化循环的控制变量(也就是循环的起点)
表达式2用于指定循环结束的条件(循环的终点【循环是否终止的判断】)
表达式3用于每次循环后变量的重新赋值(循环从起点到终点的方式)
for语句特点:
1、非常灵活
2、使用最广泛
3、for形式有很多种
-------------------
for语句的几种形式
1、标准形式
for(int i=0;i<count;i++)
2、变量在外的形式
int i=0;
for( i=0;i<count;i++)
3、变量在外,变量赋值在内
int i=0;
for(;i<count;){ i++;}
4、变量在外,变量赋值和循环终止在内
for(;;)
{
if(i<count)
break;
i++;
}
------------------------
通过上面的for的几种形式说明for语句是很灵活和很广泛
--------------------------
使用for循环时要注意的
1、变量的初始值
2、终止条件
3、变量的重新赋值
=======================================
二十一章:复习数组
数组:
一组相同类型的数据用一个变量来表示,这个表示就是数组。
数组可分为:一维数组、二维数组以及多维数组
数组相对于其他集合来说的特点:访问速度极快。
数组的定义
1、数组的声明
语法:
数据类型[] 数组名称;//声明
2、数组的创建
语法:
数组名称 = new 数据类型[数组的长度];//这里的数据类型要和声明的数据类型一致
3、数组的初始化
数组名称[数组的索引] = 同类型的值;
-----------------------------------
示例:
int[] age;//声明整型数组
age=new int[3];//数组的创建(分配内存空间)
age[0]=12;age[1]=16;age[26];//数组的初始化赋值
-------------------------------------
数组声明创建的简化语法
数据类型[] 数组名称 = new 数据类型[]{值1,值2,,....值n};//动态初始化
数据类型[] 数组名称 = {值1,值2,,....值n};//静态初始化
-----------------------------------
数组的遍历一般使用循环进行
对于类似于数组这种集合C#中提供了特别语句
foreach语句针对于集合的遍历
语法:
foreach(集合的数据类型 item in 集合){循环体语句;}
其他学过的任何循环都可以对数组进行遍历。
只不过由于数组的遍历是通过索引完成的因此,for循环是最适合的。
------------------------------------
数组排序:
排序的算法有很多,但是我们要求的主要是冒泡排序,
核心思想:
将相邻的两个元素进行比较,然后交换两个元素的位置,依次这样直到结束。
目的:将杂乱的数组元素按照一定规则排列(升序/降序),方便后面的查找。
二十二章:函数参数和返回值
函数可以帮助进行模块化设计。
前提条件就是对问题域,分析找出组成问题域的关键点(子问题)。
分而治之。以大化小。
函数的参数:
函数运算时需要参与运算的值(外部的),被称为参数。
函数的参数是主调函数与被调函数进行数据传递的主要渠道,
函数头上的块级注释其实就是对函数的简单说明,在调用时会出现提示,提示中的消息就是注释的内容。
形参和实参
形参是函数定义时出现,主要是用于约束传入数据的类型
实参是函数被调用时出现,主要是按照形参的约束传递数据。
实参是受到形参的约束的。这个约束主要是体现在数据类型上。
为啥叫形参列表或实参列表,是因为,函数定义时对参数的个数并没有限制,因此把这种就称为:形参列表或实参列表。
参数传递时是受到形参的约束,除了数据类型的约束外还有参数数量的约束。
形参还有顺序的约束,实参一定要和形参的顺序是一致的。
在形参数据类型相同的情况下,顺序并不会被检测。只有形参的数据类型不一样的情况下才会对实参的顺序检测。
当实参的数据类型和形参的数据类型不一致时必须要保证实参是可以隐式转换或显示转换的才行,否则就会出错。
===============================================
参数传递的方式:
1、值传递:就是将传入的值复制一份,然后传入到函数中,这种是默认传递方式。
2、引用传递:需要ref关键字,作用是将值的内存地址专递到函数中。这种传递方式也称为:引用传递
二十三章:函数重载
什么是函数重载?
一般情况下,函数的名称是反映函数实际功能和任务。
C#语言中不允许存在一个类中定义多个同名函数。
为了解决这个矛盾微软提供了函数重载这个技术。
允许我们定义多个同名(函数名称)函数
重载允许我们在一个类中指定同一个函数的不同版本,这些函数都具有相同的名称(我们看来),仅仅由函数的签名来区分这些不同的版本。
函数签名是编译器去识别的。
================================
函数重载运用的条件是:
1、函数的参数类型不同
2、函数的参数顺序不同(形参的类型不同)
3、函数的参数个数不同
满足以上的三个条件就可以运用函数重载。
函数重载时,形参的名称要符合命名规则,但是最重要的是形参的类型,因为形参类型才是约束实参的规则。
函数重载的识别规则是:整个函数定义的头部不包含函数体。
函数签名示例:[访问修饰符] [static] 返回值类型 函数名称(形参列表) <<<<-----就是函数签名
编译器是通过函数的签名来区别函数重载的,这样编译器才可以准确的找到对应的函数,达到重载的目的。
=============================
函数重载的几种可能:
1、形参的个数不同,但类型相同,顺序相同,可以发生重载
2、形参类型不同,个数相同,顺序相同,可以发生重载
3、形参顺序不同,类型一定要不同,个数相同,可以发生重载
======================================
函数的几种形式:
1、有参数无返回值:[public] [static] void 函数名称(int num)
2、有参数有返回值: [public] [static] int 函数名称(int num)
3、无参数无返回值: [public] [static] void 函数名称()
4、无参数有返回值: [public] [static] int 函数名称()
以上就是函数的四种形式(写法)
=====================================
函数的动态数组参数:
1、参数的类型是一个数组类型
2、参数前面加上params关键字
满足以上的两个条件,就能够创建动态数组参数的函数
动态数组参数能够将函数的参数由有限个数变为无限个数
也就是说如果使用动态数组参数则函数的参数你可以随意的传任意个同类型参数
===================================
动态数组很方便,但是不是无限使用的,它是有一些限制的:
1、定义函数时参数列表中,最后一个
2、定义函数时,动态数组参数只能有一个。
二十四章:字符串
1、字符类型在C#中表示为一个Unicode字符,是一个结构体(struct)
因为计算机是说英语的人发明的,所以英文在计算机中只占一个字节,但是中文或亚洲的语系不能直接在计算机上使用,因此推出了各种编码,其目的就是为了让亚洲的语言可以在计算机上使用,所以发明了双字节编码格式,这样就可以容纳全球的语系。
英文还是占一个字节,中文或其他亚洲的语言就是双字节表示,比如大家见过的乱码,其实就是因为双字节中某一个字节坏了的原因。
在C#中字符是属于值类型的,存储在栈中,字符类型是可以直接转为整数类型。
-----------------------------------------
C#中的转义字符
"\" <<---这是转义字符
可以把特殊符号(语言中已经指定使用的符号或字符转为普通字符)
也可以出现一些特殊的效果。
=========================
2、字符串
字符串是Unicode的字符的有序集合,主要用于表示文本,并且该值是不可以改变的。
字符串一旦赋值是不能更改的,但是字符串不是常量,因此编译器会在赋值时生成一个相同的字符串来接收新值并且将旧的字符串变量给删除掉。因此在外部看起来就像是赋值成功了。
常用属性:
Length属性用于获取字符串中包含字符的个数也就是字符串的长度。
通过这个属性我们可以使用循环遍历字符串中所有的字符。
常用的方法:
Trim()用于去除字符串两端的空白。不能去除字符串中间的空白
EndWith()用于从字符串尾端开始查找匹配的字符串。
IndexOf()用于搜索指定的字符串在目标字符串中首个匹配的索引值
LastIndexOf()用于从尾部开始搜索第一个匹配的字符串的索引值
Substring()用于从一段字符串中截取指定的一部分出来。
重载版本:
Substring(startIndex)
Substring(startIndex,count)
Split()用于分割字符串,通过指定的分割点字符来做为分割的依据。分割后产生一个字符串数组
string user = "张三,男,2010-10-01,189138338438,zs@sohu.com";
string[] UserInfo = user.Split(',');
Replace()用于替换指定的字符串
string str="世界你好";
string newstr = str.Replace("你好","今天你吃了吗?");
Remove()用于删除指定位置的字符串
str.Remove(2);<-----这个参数指定从字符串的第几个位置开始,将后面的全部删除
str.Remove(2,2)<-----第一个参数是开始的位置,第二个参数是删除多少个字符
=========================================================
字符串是引用类型,但是使用时一般看成值类型来用。
=========================================================
String和string本质是一样的,只不过string是String类的一个别名
===========================================================
动画:
控制台是字符界面,因此不具备复杂的绘图能力。
动画原理:
每帧一个图案,间隔一定的时间显示,然后形成动画的效果。
C#控制台中实现可以使用不间断循环语句加上线程的暂停时间达到动画的效果。
1、使用线程暂停实现
2、使用time实现
原理:通过时间的间隔触发相应的函数达到动画的效果
小提示:
方块图标表示函数
闪电图标表示事件
扳手图标表示属性
-------------------------
以上另种方法都可以实现控制台的动画,但是第一种死循环模式会照成CPU大量的占用。但是语法简单,实现容易。
第二种时间间隔模式不会照成CPU大量占用,但是逻辑比较复杂。而且必须要用全局变量,因为每次都会重新调用事件函数,函数里面的内容都会初始化。
二十五章:异常处理
1、什么是异常?
指程序运行过程中发生的异常事件(不正常事件)
这些事件的组成是由:
a、硬件问题
b、软件问题
异常是可以处理(不是全部)
在C#中将常见的异常封装为一系列的类。使用时直接调用即可。
常见的异常:
1、Exception <----异常的总类(祖先类)
2、SystemException <----系统异常类
3、ArgumentException <----参数异常类
4、ArithmeticException <----算术导致的异常类
5、IOException <----输入输出异常(流的异常)类
6、IndexOutOfRangeException <----索引超出异常(数组索引越界)
7、DivideByZeroException <----除零异常
8、OverflowException <----运算结果过大,超过目标类型的范围。
9、FormatException <----输入字符串格式不正确异常
--------------------------------
为什么要处理异常?
1、对用户来说体验不友好
2、程序会因此死掉,所以未保存的数据就有可能丢失。
3、程序因为未知问题导致数据的丢失。
---------------------
异常的处理不是异常出现后的处理而是预先估算可能出现异常的地方事先做出处理的方式。
C#中处理异常使用的抛接机制?
程序遇到异常会将异常抛出,如果没有处理则继续抛出,直到操作系统收到异常信息做出处理。
如果操作系统没有做出异常的处理那么就会导致系统的死机。因此现在的操作系统对于程序抛出的异常一般都是直接杀掉异常程序的进程从而保证操作系统的正常运行。
那么在C#语言中提供了抛接机制来处理异常
语法:
try
{
//异常代码预估
}catch(异常类型 异常变量)
{
//异常处理代码
}
将可能发生异常的代码放到try的模块中进行测试,一旦代码出现了异常则下面得catch模块会主动拦截并程序的流程转向到此处进行处理,这样一来异常的代码就被处理了。所以就不会把程序的异常抛给操作系统处理,由于已经处理了异常所以程序就可继续运行或是正常退出。这样就保证了程序的健壮性。
catch后面的小括号中的内容并不是必须的,可以没有小括号,但是如果没有小括号也就不能得到异常的信息。如果你需要异常的信息用来判断究竟是什么异常时,异常信息就会告诉你。这样我们就可以有针对性的处理。
=========================
ps:.net 4.7.2版本认为除零是正无穷大(此种情况是数据类型为double时出现)
当整数进行除零时出现除零的异常。
================
在使用catch捕捉异常信息时可以根据由进到远的关系来做出多种异常类型的捕捉,
祖先类型:Exception放在最后一个,其他同级别异常没有先后顺序。
================================
从代码中可以看出,异常的捕捉也是一级一级的进行,最后是异常祖先类型。
======================================
以后如果涉及到程序中使用其他的资源这种情况下,一旦发生异常就会导致资源被占用,如果没有很好的处理就会导致资源被锁定了,其他程序将不能访问。
为了解决这个问题C#中提供了finally语句模块用于释放资源。
finally语句的特点:
无论有没有异常发生都将执行finally模块中的释放语句。
finally使用场景:
1、程序中使用了数据库资源
2、程序中使用了文件独占访问资源
3、程序中独占了某个网络的端口
。。。。。
以上这些只要是有使用资源的情况,都需要使用finally进行资源的释放。
=========================================
某些特殊的情况下我们需要人为抛出异常
此时我们使用throw语句来做人为抛出异常
语法:
throw new Exception("异常消息");
finally语句块中不能使用return语句,语法不允许。
哪怕在try块或catch块中使用return语句,如果有finally语句也会跳到此处执行。这是语法规则。也是编译器的规则。
二十六章:复习指导-函数
/*
* 函数就是一段特定的功能代码,将这段代码封装起来并且给一个好看的、好识别的名称(这种方式在编程语言中称为:函数/方法/子过程)
* 函数在业内也叫:最小可执行单元
* 好处在哪里呢:
* 1、方便阅读理解代码
* 2、方便修改、更新代码
* 3、方便调试,改错
* 4、代码的复用
* 5、方便设计,以及理清业务逻辑
* -------------------------------
* 函数的类别:
* 1、系统函数。由系统自带的函数
* 2、自定义函数。就是由开发人员根据需要自己封装的特定功能代码块
* ---------------------------
* 函数的语法:
* [访问修饰符] [static] 返回值类型 函数的名称([形参列表])
* {
* //函数的功能代码
* }
* 语法说明:
* []括号代表是可有可无,不是必须的
* 没有[]括号括起来的都是必须元素。
* 调用无返回值函数的基本语法:
* 函数名称(实参列表);//<------这里的实参列表是取决于(受到)形参列表的(约束)
* 调用有返回值函数的基本语法:
* 返回值数据类型 变量名 = 函数名称(实参列表);//<------这里的实参列表是取决于(受到)形参列表的(约束)
* PS:函数的返回值是根据实际情况的需要来决定的,不是说一定有也不是说一定没有。
* -----------------------------------
* 函数的参数是主控函数(主调函数)用来和被调函数(被控函数)通讯的桥梁
* 根据参数出现的位置不同<------此处的位置是说定义时的位置和调用时的位置
* 定义时参数的位置称为:形参(形式参数)
* 调用时参数的位置称为:实参(实际传入的具体数据)
* -------------------------------------
* 函数的参数传递有两种方式:
* 1、值传递这也是C#中默认的传递方式,就是将数据的副本(拷贝)传递到函数中。 *
* 2、引用传递这个是特定需求时使用,就是将数据的内存地址传递到函数中。
* 区别:
* 值传递不会影响原数据,因为传递是副本
* 引用传递直接影响原数据,因为传递的是数据所在的内存地址
* 引用传递的语法:
* void refMethod(ref int x,ref int y){}
* 侍弄ref关键字,将数据的地址传递到函数中
* 调用时也要注明ref关键字才行
* --------------------------------
* 函数的返回值是由return语句实现的
* 函数的返回值必须和函数定义时返回值的数据类型是一致的才行
* 每个函数只能有一个返回值
* PS:通过ref也可以返回多个值
*/
二十七章:复习指导-字符串及异常处理
/*
* 函数重载是指在一个类中创建一个函数的多个版本
* 默认情况下每个类的范围内不可以声明同名对象超过一个,因为这样会发生二义性的错误,此时编译器将无法识别.
* 函数也是一样的,为了解决这一个问题,微软提供函数重载来解决这个问题。
* 函数重载是通过函数的签名来进行识别和区分,而不是通过函数名称来区分的。
* 函数签名示例:
* void Add();/int Add();<-----这种情况不是签名不同而是只识别函数名称和形参列表
* 正确的函数签名是这样的:函数名称(形参列表)/---->Add(int parm)
* 函数重载发生的三种情况:
* 1、函数名称相同,形参类型不同,其他相同或不相同都行
* 2、函数名称相同,形参个数不同,其他相同或不相同都行
* 3、函数名称相同,形参顺序不同,其他参数类型不同外,其他相同或不相同都行
* PS:严格来说重载是只和形参相关,是通过形参来识别,上述的三种重载情况可以构成函数签名不同
* 一下情况和函数重载无关:
* 1、返回值类型不同和重载无关
* 2、访问修饰符不同和重载无关
* 3、和函数所属(static)也和重载无关
* 函数和类的注释不能只用简单的单行、多行注释,应该使用///的块级注释,因为块级注释可以在调用函数是产生注释内容的提示
* ==============================================================
* 字符是指Unicode编码的一个文本或符号
* 字符类型中包含很多实用的函数:
* 1、char.IsControl()<----用于判断是否属于控制字符
* 2、char.IsDigit() <----用于判断是否是十进制数字
* 3、char.IsLetter()<----用于判断是否是字母
* 4、char.IsLower()<----用于判断是否是小写字母
* 5、char.IsUpper()<----用于判断是否是大写字母
* 6、char.IsWhiteSpace() <---用于判断是否是空白字符
* 。。。。。。
* ----------------------------------------------------------
* 字符串是一串Unicode字符组成,它是引用类型,但是表象是值类型,它同样提供了丰富的函数来供开发者使用:
* 字符串属性:
* Length<---用于获取字符串的长度,也就是字符串中包含的字符个数,是常用的属性,它是针对于具体的某个字符串的
* 字符串函数:
* 1、Trim()<---用于消除字符串两端的空格
* 2、EndWith()<----用于指定字符串匹配末尾是否一样
* 3、IndexOf()<----用于查找指定字符串在目标字符串中第一个匹配的索引位置,匹配成功返回索引,失败返回-1
* 4、LastIndexOf()<----用于查找指定的字符串在目标字符串中最后一个匹配的索引位置,匹配成功返回索引,失败返回-1
* 5、SubString()<----用于指定开始的位置和长度来截取字符串,也可以只指定开始位置,然后截取
* 6、Split()<----用于指定的字符或字符串把目标字符串分割为字符串数组
* 7、Replace()<----用于使用指定的字符串替换目标字符串中的匹配的内容
* 8、string.IsNullOrEmpty()<----用于测试字符串变量是否是空值还是空字符串
* 9、Contains()<----用于测试指定的字符串是否出现在目标字符串中
* 10、.Clone()<----返回对这个字符串实例的引用(克隆方法)
* 11、CompareTo()<----与指定的object比较,并指示是在object之前还是之后
* ----------------------------------------------------------------------
* 异常处理
* 异常就是不正常的情况出现,放在程序中就是程序不按照正常的设计逻辑去运行。这就是异常。
* 也就是说程序中出现了设计逻辑不完整的地方。
* 异常处理就是将可能发生异常代码事先进行预估计,然后进行处理。
* 异常处理目的:为了程序能够不间断的执行,而不会因为异常导致程序死掉。
* 因为操作系统的规则是一旦某个程序威胁到操作系统的正常运行了,那么操作系统会将这个程序干掉,杀死该程序的进程。
* 异常的出现会一直向上抛出,直到被处理,否则就会引来操作系统进行干预。
* 在C#中异常是一种结构化、统一的和类型安全的错误处理机制
* C#异常处理的特征:
* 1、所有的异常必须是System.Exception类或者是其子类的实例来表示
* 2、使用try...catch结构来编写逻辑代码和异常处理代码
* 3、使用finally块来执行正常或异常都要执行的代码(一般情况下用于释放资源)
* 常见异常类型:
* 1、Exception:异常的总类,所有的异常都是它的子类
* 2、System.Exception:系统异常类
* 3、ArgumentException:参数异常类
* 4、IOException:输入输出异常类
* 5、IndexOutOfRangException:索引超出范围异常(访问数组元素越界)
* 6、DivideByZeroException:除零异常(整型会出现异常,浮点会出现正无穷大)
* 7、OverflowException:数据溢出异常
* 8、FormatException:提供字符串格式不正确异常
* 异常类属性:
* Message属性:用于提供异常类型对象的详细描述
* StackTrace属性:用于追踪异常的堆栈信息。
* C#中异常的引发方式有两种:
* 1、系统引发(由程序正常执行时逻辑不完整导致的异常)
* 2、主动引发异常:这是由代码中主动使用Throw语句抛出的异常
* */
二十八章:CRS一体机
任何一个项目都有几个步骤:
1、可行性研究
包含项目开始前的各种准备工作情况,以及风险收益成本等等。
2、需求分析
目的:弄清楚要做什么?来源于可行性报告
3、概要设计
整个项目的总体结构和模块分析出来。来源于需求分析
4、详细设计
项目中每个小的模块的设计。来源于概要设计
5、项目计划
人员的分配,项目周期(进度规划),任务的分配。
6、开工
开始工作,人员开始按计划在规定时间内完成各自的任务。
---------------------------------------------------
CRS一体机项目的功能:
1、开户和登录
2、查询余额
3、存款、取款
4、转账
5、密码修改
二十九章:初探类与对象
面向对象出现前,是结构化程序设计它是面向过程的,问题看成一系列的任务,函数是用于完成这些任务主体,函数式解决问题。焦点就是设计函数。
什么是面向对象?
是一种编程架构,特点:重用性更高,更加灵活,扩展性更强
C#语言是一种面向对象的编程语言,它的设计思想是将要解决的问题里面的相关对象分析总结出来,抽象出它特征和行为。
面向对象中一个重要的东西:
类----》class
描述一组具有相同特征和相同行为的对象。如果在程序中就表现为类型。
抽象是分析观察物质的得到的结论。是智能生物所具备的特征之一。
类和对象的关系
类是一个抽象的概念,是一组具有相同特征和行为的对象集合。
对象是类具体表达。
类和类的成员之间是可以访问的,使用访问修饰符进行访问控制的
C#提供了五种访问修饰符
public --------------》公共的,谁都可以用
private--------------》私有的,只有自己可用
protected------------》受保护的,只有自己和自己的后代可以用
internal-------------》程序集内部,进当前的程序可用
protected internal---》程序集派生的类可以访问
-------------------------------------
类的成员:
1、字段
功能:用于数据的存储,用于描述数据的。
语法:
[访问修饰符] 数据类型 字段名称;
例:public string Name;//这个字段描述了一个名称,存储的数据类型是字符串类型
2、方法(函数)
功能:执行类型的动作(操作),用于描述此类型的对象它的行为
例:
[访问修饰符] 返回类型 方法名称/函数名称(形参列表){方法体;}
3、属性
功能:用于存储数据,是字段的升级。比字段更加安全,可以检测字段的数据是否安全合法。
4、其他对象
功能:包含其他特殊对象完成特殊功能的。
----------------------------------------------
对象的操作
步骤:
1、创建对象的实例
首先要有对象的类型。
例如:
//设计一个猫类
class Cat{ int age;string name;bool sex; public void Talk(){Console.WriteLine("喵喵面哦");}}
//创建猫类的实例
Cat boss = new Cat();//就是创建类型的一个实例
说明:
在面向对象的编程世界中对象不是首先存在的,必须先创建类型,然后再由类型衍生出对象,这个过程就叫:实例化对象。实例化对象的过程中必须向系统申请空间(内存空间)向系统申请空间的关键字就是 “new”。
创建的对象属于引用类型,所以存放在“堆里面”。
2、使用对象
boss.Talk();//调用Cat类型的实例boss的Talk方法
对比:Console.Write();
---------------------------
设计类型时如果成员没有明确的指定访问许可时默认就是私有成员。只能内部访问,外部和继承类都不能访问。
-------------------------------------
C#是面向对象的语言,面向对象的三大主要特征:封装、继承、多态。
在现实世界中我们是能看到具体的对象的,然后通过观察抽象出对象的类型。(物以类聚,鸟以群分)。
但是在编程世界中我们是先设计类型,然后衍生出对象,所以和现实世界中是相反的。
也就是说在编程的世界中你就是“上帝”,你是无所不知,无所不能的。
三十章:类的静态成员
类的成员有哪些?
成员的分类:
1、存储数据(字段、属性、集合)
2、行为(函数/方法、事件)
3、作为标识(枚举、常量)
4、内置对象(结构体,类)
类成员的所属关系:
1、归类本身所有(static)
2、归类的实例所有(类实例化后的对象,instance)
==================================
所谓的面向对象其实就是模拟人类社会。
==================================
静态成员使用static关键字修饰的。它是属于类所有。
所有类型的实例都有的属性、字段、函数等,属于类所有。
静态成员由类进行调用。静态成员的数据是由类存储。
========================
没有使用static关键字修饰的就是实例成员。
实例成员只能由类的实例调用和存储。
===============================
静态成员只能通过类进行调用。
实例成员只能通过类的实例进行调用
============================
定义静态成员的语法:
[访问修饰符] static 数据类型 字段名称;
[访问修饰符] static 返回值类型 函数名称(形参列表){函数体;}
简单的说就是加了static关键字的成员就是静态成员,没有static关键字的就是实例成员。
================================
定义实例成员的语法:
[访问修饰符] 数据类型 字段名称;
[访问修饰符] 返回值类型 函数名称(形参列表){函数体;}
======================
静态成员的特征:
1、必须通过static关键字定义,通过类名访问
2、在内存中一个静态字段只是标识一个存储位置,无论你创建了一个类的多少实例,它的静态字段在内存中都只占同一块区域。
3、静态方法不能作用于对象,静态方法中不能直接使用实例成员,必须要通过对象名引用访问,但是可以直接访问本类的静态成员
4、静态字段的数据被类型的对象共享。
5、静态的成员速度快,但占内存,就像数据的缓存一样,经常使用的数据我们应该将它们缓存。
======================
实例成员特征:
1、实例成员不能添加static关键字定义,通过对象名访问
2、类的实例成员属于类的对象所有,每创建一个类的实例,都在内存中为实例字段开辟了一块区域。类的每个对象,分别包含一组该类所有的实例字段的副本。
3、类的实例方法直接作用于类的对象,在实例方法中可以直接访问本类的静态成员和实例成员
4、调用完毕后会自动释放资源,这样可以节省内存空间。
5、实例的速度比较慢,但是灵活,而且不占内存,因为只要没有对这个实例的引用了,就会回收释放资源
============================
主意:
设计类型时要知道你所设计的类型是否是辅助类,是否有方法/函数是频繁的调用,如果是则可以考虑设计为静态的,另外如果某个字段的内容是作为标识并且在整系统中都会用到的情况下也可以考虑用静态字段
三十一章:构造函数与属性
1、构造函数
说道构造函数就不得不说一下对象的生命周期。
对象的生命周期一共有三个阶段:
构造阶段:是对象诞生,通过构造函数完成新对象的初始化。
正常使用阶段。
析构阶段:对象使用完成后,空置没有任何一个引用了,那么系统的垃圾回收机制就会将这个对象收回并释放这个对象所拥有的资源。C#由析构函数完成。
-----------------------------------
构造阶段使用的是构造函数
构造函数是一个特殊的方法和普通的函数不同,因为构造函数是由系统调用。当进行new关键字的时候,系统就会去调用构造函数。因此构造函数是没有返回值的连void都不行。
构造函数除了没有返回以及是由系统自动调用外其余的和普通函数没啥区别。
-----------------------------------
构造函数的特征:
1、必须与类同名
2、构造函数不能声明返回类型(连void也不行),不能返回值
3、构造函数总是public类型,私有的private表示不能被构造
如果是私有构造函数则类中一定会有静态成员。
4、构造函数仅做初始化的事情不要做其他与初始化无关的事情。
5、构造函数可以重载,从而提供初始化对象的不同方法。
6、构造函数是对象实例化时由编译器系统自动调用,不能显示的调用构造函数。
7、如果定义类时没有定义构造函数,则系统会自动生成一个默认构造函数。
---------------------------
如果没有自定义的构造函数则编译器系统会默认提供一个,功能就是初始化对象里面的成员。
初始化什么数据值:
数值类型:
char初始化为:‘0’
数字int float,double,decimal初始化为:0
引用类型:null《--- 空值/空对象
类型:默认值
-------------------------
所谓的构造函数初始化成员:
其实就算你自定义的构造函数中没有为字段、属性等赋初值,编译器还是会给初始化的值。也就是说无论如何,对象成员在new的时候都会有默认值
-------------------------
构造函数的重载
性质:和普通函数的重载一样的,但是构造函数由于必须与类同名,因此如果多余一个天然就只能重载。
----------------------
在面向对象编程中this代表当前对象的一个引用。
就相当于假定你这个类已经有一个对象了,this表示这个对象。
-----------------------------
属性?
面向对象的封装性原则要求不能直接访问类的数据成员,如何访问类的私有成员呢?
为了解决这个问题C#提供了一个称为:属性的访问器来完成这个功能。
为啥要用属性呢?
面向对象的设计中,主要是模拟现实社会中物质的特征,这个特征有一个词:就是属性,编程世界中借鉴这个词,这就是属性的由来。
从安全性的角度出发,字段是直接赋值或取值的,那么这里就有一个安全性的问题,非法的数据可以直接赋值给字段,如果不小心就会导致错误的发生。
将字段封装起来就能够有效的避免这个问题,这个对字段的封装就是属性。同时将字段设为私有的,封装的属性设为公共的,当数据赋值时就可以在属性中进行检测,同理取值时也可以通过属性检测。
---------------------------
属性中使用get、set访问器来对字段进行访问。
---------------------------
属性怎么写:
1、手写
2、vs生成
-----------------------
属性中有一个隐含变量是:value
它是用于接收传入的值,它的类型是根据属性的类型的变化而变化的。
----------------------------
而属性其实就是一种特殊的函数,因为在编译器中是没有属性这个东西的,因此.net
在编译时会将属性编译为函数。
-------------------------------
很屌的写法:
[访问修饰符] 返回值类型 属性名称{get=>字段名;set=>字段名;}
便捷写法的特点:速度快,形式简便
[访问修饰符] 返回值类型 属性名称{get;set;}
便捷写法还少了定义字段。(推荐写法)
属性的三种写法:
1、原始写法
私有的字段类型 私有的字段民;
[访问修饰符] 返回值类型 属性名称{get{return this.字段名;}set{this.字段名=value}}
2、屌的写法
私有的字段类型 私有的字段民;
[访问修饰符] 返回值类型 属性名称{get => 字段名; set => 字段名= value;}
3、便捷写法
[访问修饰符] 返回值类型 属性名称{get;set;}
------------------------
因为属性也是类的成员因此也分为:静态和非静态
属性的访问:
1、访问静态属性
类名.属性名
2、访问实例属性
对象名.属性名
------------------------
字段是不能做到只读或只写
但是属性可以做到
作用的体现:
1、在赋值或取值时可控制
2、可以控制只读、只写
----------------------
1、只读属性的写法
便捷写法
[访问修饰符] 属性的数据类型 属性名称{get;private set;}//可以在类中进行赋值
[访问修饰符] 属性的数据类型 属性名称{get;}
原始写法
[访问修饰符] 属性的数据类型 属性名称{get{return 属性名称};}
屌的写法
[访问修饰符] 属性的数据类型 属性名称{get => 字段名称;}
2、只写属性的写法
便捷写法
[访问修饰符] 属性的数据类型 属性名称{private get; set;}//可以在类中进行取值,一定要有get访问器,因此可以将get访问器设置为私有的
原始写法
[访问修饰符] 属性的数据类型 属性名称{set{ 属性名称=value};}
屌的写法
[访问修饰符] 属性的数据类型 属性名称{set => 字段名称=value;}
三十二章:类的继承
1、什么是继承?
通俗的来说就是子承父业。
你得到了和你有着最亲密的血缘关系的直系长辈的财富。
你还得到了相关的知识和经验以及性格。
现实社会中的继承包括有两大类:
1、非物质类
2、物质类
因为物质类而互相伤害,目的是为自己获取最大利益。这个其实就是人的自私性。
在编程世界中继承是指一个类建立在另一个类的基础之上的,也就是说一个类被另一个类继承了。
被继承的类称为“基类/父类”,继承的类称为“派生类/子类”
===============================
前面我们学习的访问修饰符:
1、public(公共的)
2、private(私有的)
3、protected(受保护的《-----只能被自己或自己的子类使用)
================================
继承的好处:
1、代码的复用(无需从零创建,可以在已有的基础上进行扩展)
2、继承的传递,可以无限传递(一层一层往后进行传承)
3、
=================================
C#这种语言比较纯粹,不支持多继承,C++是支持多继承的
因此C#语言也称为‘单根继承’语言。
============
C++多继承思想应该来源于现实中建筑行业或其他行业,
C#更多是借鉴人类社会的情况。
=====================
C#中继承是可以传递的,同时C#只有一个特殊的基类---》object,
这个类是C#所有类型的基类。
===================
步骤:
1、首先定义基类
2、然后才能定义派生类
定义基类语法:
和定义普通类是一样的,从设计考虑上是不一样的。
[访问修饰符] class 基类名称{基类的成员}
定义派生类的语法:
[访问修饰符] class 派生类名称:基类名称//通过:符号进行继承
{派生类的成员}
--------------------
派生类天然拥有基类的所有非私有成员(其实是所有成员,只不过私有的是不能用的)
=======================
类继承的原则:
除了Object外,每个类有且只有一个直接基类,如果没有显示的指定直接基类,它的直接基类就是Object。Object是没有任何直接或间接的基类,因此它是终极基类
=============================
因此所有的对象都可以直接转为Object,但是反过来就要进行显示转换了,而且还不保证转换成功
====================================
装箱/拆箱
1、装箱
将某一个对象直接转为Object。这个过程就成为“装箱”
2、拆箱
将一个已经装箱了的对象还原成它的真实类型。这个过程就成为“拆箱”
------------------
来源于程序之间的数据传递。
例如:QQ程序和阿里的程序之间互相传递数据,QQ程序中的一个对象的类型在阿里的程序中可能没有,因此将QQ的要传递的数据装箱为Object,阿里的程序中也有基类--Object,这样一来两个程序的数据类型就达成一致,那么就可以互相传递数据了。
----------------------------
基类中的非私有成员派生类都可以访问。
但是受保护的(protected)成员只能在派生类中使用。
公共成员(public)派生类和外部类都可以使用。
----------------------------------
外部能够使用的只能是公共的(public),除此之外都不能在外部访问。
------------------------
派生类除了拥有基类的成员之外,还可以有(扩展)自己的成员
----------------
C#中只支持单根继承,不支持多继承。
-------------------------
但是C#中不能进行循环继承。
class A:C
{}
class B:A
{}
class C:B
{}
以上这种就是循环继承,是不允许的。
------------------------
庸俗的来讲(穿越小说中可以发生的悖论)
主角穿越后干掉了自己的爷爷的爷爷的爷爷。自己是存在还是不存在?
三十三章:复习面对对象
1、巩固类和对象
1.1、什么是类?
一切相关的具有相同特征和行为的对象,统一一个称呼:类
1.2、什么是对象?
对象就是类的具现化,如果把类当做图纸,那么对象就是根据图纸出来的产品。
例如:一辆汽车,首先是设计图纸,根据设计图纸进行产品的生产(具现化)
1.3、类的成员
划分方式:
从功能上划分:数据成员(存储数据),方法成员(函数)
从所属关系上划分:静态成员和实例成员
静态是归类所有,直接通过类名点成员名进行调用
实例成员归类的实例所有,通过类的实例点成员名进行调用
静态成员和实例成员的区别
静态成员由于是归类所有因此在内存中每个成员只有一个空间所以是共享的。当多个对象去访问时会出现后来的修改会覆盖前面内容。
实例成员由于是归类的实例所有因此内存每个实例都有自己的空间,互相不会受到干扰。
----------------------
语法示例:
类名 对象名 = new 类名();//------实例化一个对象
对象名.成员名(数据成员/方法成员)
-----------------
类名.成员名(数据成员/方法成员)//----静态的调用方法
-------------------------------------------
C#中使用new关键字去实例化对象
意思就是通过new关键字向系统申请内存空间。
对象是C#语言的核心,对象根据内存空间的位置分为:值类型、引用类型
--------------------------
现实世界中除了极少数的生物外,其余的生物都有三个过程:
构造阶段、正常使用阶段、析构阶段
和程序中一样。
构造阶段作用:
1、申请空间
2、初始化成员
正常使用阶段:
根据需要进行正常使用
析构阶段:
当对象没有任何引用了,系统就将对象回收并释放对象所占用的空间。
构造函数的语法要求:
1、和类同名
2、不能有返回类型,void的也不行
3、构造函数是可以重载的
4、构造函数也可以有访问修饰符(一般是公共的,私有的构造函数适用于特殊用途)
------------------------------------
类的成员:
1、数据成员
作用:存储数据的
分为:字段、属性
字段其实就是类的变量,但是是属于类级别
属性其实就是将字段设为私有,但是留出公共的访问接口,这个接口就称为:属性,它可以验证数据的安全性
===========================================================
在C#程序中只有变量可以存储数据(基础类型[int、double、char。。。。。。],对象类型)
面向对象这里统统的称为“对象”。
================================
使用属性来控制数据的流入和流出(赋值、取值)
变量本身是无法控制数据的合法性。通过属性进行有效的检测。
属性在C#中有多种写法:
1、原始写法
访问修饰符(私有的) 字段类型 字段名称;//私有字段
访问修饰符(公共的) 属性类型 属性名称{get{return 字段名称;}set{字段名称=value;}}
2、编译器写法
访问修饰符(私有的) 字段类型 字段名称;//私有字段
访问修饰符(公共的) 属性类型 属性名称{get=> 字段名称;set=>字段名称=value;}
3、便捷写法
访问修饰符(公共的) 属性类型 属性名称{get;set;}
------------------------
静态的属性不能访问实例的字段。
实例的属性是可以访问静态的字段。
-------------------------------
静态属性、实例属性其实最终决定的是字段。
静态的对象是空间共享的,实例的对象空间是独立。
--------------------------------
静态成员一般是做标识用的,静态方法用于公共使用仅仅是实现功能而不保存数据的。
静态的字段由于空间共享因此后面的赋值会覆盖前面的内容。(和变量一样)
-----------------------------------------------
面向对象的三大特性:封装、继承、多态
---------------------------------------------
类的继承
一个类建立在另一个类的基础之上。
被继承的类称为:基类(父类)
继承类称为:派生类(子类)
继承的优点:
1、代码的复用
2、减少出错的几率
3、降低成本
-------------------------
实现继承
定义基类:
class 基类名称 { 基类成员 }
定义派生类:
class 派生类名称 : 基类名称 { 派生类扩充成员 }
派生类对象访问基类成员:派生类对象名.基类成员名
-----------------------------------------------
类的成员中
数据成员一般都是名词
方法成员一般都是动词
-----------------------------
继承之后
派生类拥有基类所有的非私有成员,同时还可以拥有自己的成员达到扩展的目的。
--------------------------------------------------------
派生类从基类得出并且可以有自己的成员
在程序世界中,派生类可以看成基类,是隐式转换。就像Object一样
----------------------------
由于有了继承因此多态就出来了。课堂上的例子就是多态的一种形式。
浙公网安备 33010602011771号