C#基础学习(Mario老师)

由浅入深,循序渐进

本次课程,以零基础程序员为对象,从C#基础开始学起,掌握所有C#核心基础后,学习开发一个小项目。讲解过程我会步骤详尽,不求速度,只求质量。

实力典型,轻松易学

通过例子学习是最好的学习方式,我将通过“一个知识点,一个例子”的方式,透彻详尽地讲述开发过程当中所需的各类知识,也会给大家分享我在原来开发过程当中的一些趣事,让大家更容易接受代码,更容易学会代码。

致大家

我们本着科学严谨的态度,将会用最简单的语言,来讲解结构复杂的代码,争取能够通过接下来的学习,大家能够掌握到C#语言的开发基础,满足外面公司的基础需求,真正做到从“小白”到“程序员”的蜕变!!!

一、.NET平台和C#语言的介绍

C#是一种面向对象的编程语言,主要用于开发可以运行在.NET平台上的应用程序。C#的语言体系都构建在.NET框架上,近几年,C#语言的简单、现代、面向对象和类型安全等特点正在被越来越多的人认同。

C#语言及其特点

C#是微软公司设计的一种编程语言,是从C和C++派生来的一种简单、现代、面向对象和类型安全的编程语言,并且能够与.NET框架完美结合。C#具有以下突出的特点:
(1)语法简洁。不允许直接操作内存,去掉了指针操作。
(2)彻底的面向对象设计。C#具有面向对象语言所应有的一切特性:封装、继承和多态。
(3)与Web紧密结合。C#支持绝大多数的Web标准,例如HTML、XML、SOAP等。
(4)强大的安全性机制。可以消除软件开发中常见的错误(如语法错误),.NET提供的垃圾回收器能够帮助开发者有效地管理内存资源。
(5)兼容性。因为C#遵循.NET的公共语言规范(CLS),从而保证能够与其他语言开发的组件
兼容。
(6)灵活的版本处理技术。因为C#语言本身内置了版本控制功能,使开发人员更加容易地开发和维护。
(7)完善的错误、异常处理机制。C#提供了完善的错误和异常处理机制,使程序在交付应用时能够更加健壮。

认识.NET Framework/.NET Core

.NET Framework是微软公司推出的完全面向对象的软件开发与运行平台。.NET Framework具有两个主要组件:公共语言运行时(Common Language Runtime, CLR)和类库。

公共语言运行时:公共语言运行时(CLR) 负责管理和执行由.NET编译器编译产生的中间语言代码( .NET程序执行原理如图1.1 所示)。由于共语言运行库的存在,解决了很多传统编译语言的一些致命缺点,如垃圾内存回收、安全性检查等。

类库:类库我们比较好理解,就好比一一个大仓库里装满了工具。类库里有很多现成的类,可以拿来直接使用。例如,文件操作时,可以直接使用类库里的IO类。

.NET Core是适用于 Windows、Linux 和 macOS 的免费、开源托管的计算机软件框架,两者最直接的不同点便是他们的运行环境,.NET Framework只能在Windows环境下运行,但.NET Core是跨平台的

C#的应用领域

游戏软件开发

桌面应用系统开发

智能手机程序开发

Web应用开发

云开发

物联网IOT

人工智能AI

二、Visual Stuido开发工具的安装

下载地址:https://visualstudio.microsoft.com/zh-hans/vs/

C#基础详解教程 - 图1

安装时,必须联网

三、Visual Stuido开发工具的介绍(宇宙第一IDE)

Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等。所写的目标代码适用于微软支持的所有平台,包括Microsoft Windows、Windows Mobile、Windows CE、.NET Framework、.NET Compact Framework和Microsoft Silverlight 及Windows Phone。

四、VS项目结构解读

程序员的第一行代码Hello World!

命名空间

C#程序是利用命名空间组织起来的。命名空间既用作程序的“内部”组织系统,也用作向“外部”公开的组织系统(即一种向其他程序公开自已拥有的程序元素的方法)。如果要调用某个命名空间中的类或者方法,首先需要使用using指令引入命名空间,using指令将命名空间名所标识的命名空间内的类型成员导入当前编译单元中,从而可以直接使用每个被导入的类型的标识符,而不必加上它们的完全限定名。

C#中的各命名空间就好像是一个存储了不同类型的仓库,而using 指令就好比是一把钥匙, 命名空间的名称就好比仓库的名称,可以通过钥匙打开指定名称的仓库,从而在仓库中获取所需的物品。

类是一种数据结构,它可以封装数据成员、函数成员和其他的类。类是创建对象的模板。C#中所有的语句都必须位于类内。因此,类是C#语言的核心和基本构成模块。C#支持自定义类,使用C#编程就是编写自己的类来描述实际需要解决的问题。
类就好比医院的各个部门,如内科、骨科、泌尿科、眼科等,在各科室中都有自己的工作方法,相当于在类中定义的变量、方法等。如果要救治车祸重伤的病人,仅一一个部门是不行的,可能要内科、骨科、脑科等多个部门一起治疗才行,这时可以让这几个部门临时组成-一个小组, 对病人进行治疗,这个小组就相当于类的继承,也就是该小组可以动用这几个部门中的所有资源和设备。

Main()方法

Main()方法是程序的入口点,C#程序中必须包含一一个Main(方法,在该方法中可以创建对象和调用其他方法,一一个C#程序中只能有一个Main()方法,并且在C#中所有的Main()方法都必须是静态的。
C#是一种面向对象的编程语言,即使是程序的启动入口点,它也是一个类的成员。由于程序启动时还没有创建类的对象,因此,必须将入口点Main()方法定义为静态方法,使它可以不依赖于类的实例对象而执行。
Main()方法就相当于汽车的电瓶,在生产汽车时,将各个零件进行组装,相当于程序的编写。当汽车组装完成后,就要检测汽车是否可用,如果想启动汽车,就必须通过电瓶来启动汽车的各个部件,如发动机、车灯等,电瓶就相当于启动汽车的入口点。

标识符

可以简单理解为一个名字,用来标识类名、变量名、方法名、数组名、文件名的有效字符序列

关键字

是C#语言中已经被赋予特定意义的一些单词,不可以把这些单词当作标识符来使用

语句

语句是构造所有C#程序的基本单位。语句可以声明局部变量或常数、调用方法、创建对象或将值赋给变量、属性、字段,通常以分号终止。

注释

对某行或者某段代码进行说明,方便对代码进行理解与维护。

五、三种注释

三种注释

1.单行注释(//)

2.多行注释(/ /)

3.文档注释(///)

六、变量和数据类型(数据类型暂时理解为不同的容器)

int 整数类型

  1. int number=10;

float 单精度浮点型

  1. float f =3.5f;

double 双精度浮点型

  1. double d =3.1415;

char 字符类型

  1. char c ='a';

string 字符串类型

  1. string str="abcdefg";

bool 布尔类型

  1. bool b =true;

七、运算符、表达式、占位符

加+

两数相加

减-

两数相减

乘*

两数相乘

除/

两数相除

取余%

获取余数

++ —

自身加1 自身减1

前++ 后++ 前— 后—

单独使用无差异,和表达式配合使用,前++,先给变量加1,再进行运算,后++,先用变量的值进行运算,再加1

+= -= *= /=

大于 小于 > < >= <= == != (比较运算符)

与&& 或|| 非!

八、Console.ReadLine()和转义符

Console.ReadLine()是什么?
是指让用户输入

转义字符

转义符 说明
\n 按Enter键换行
\t 横向跳到下一指标位置
\“ 双引号
\b 退格
\r 按Enter键
\f 换页
\\ 反斜线符
\‘ 单引号符

九、类型转换

隐式转换

隐示类型转换表

源类型 目标类型
sbyte short、int、long、float、double、decimal
byte short 、ushort、 int 、uint、 long、 ulong、 float、 double、 decimal
short int、 float、 long、 double、 decimal
ushort int、 uint、 long、 ulong、 float、 double、 decimal
int long、 float、 double、 decimal
uint long、 ulong、 float、 double、 decimal
char ushort、 int、 uint、 long、 ulong、 float、 double、 decimal
float double
ulong float、 double、 decimal
long float、 double、 decimal

显式转换

显示类型转换表

源类型 目标类型
sbyte byte、 ushort、 uint、 ulong、 char
byte sbyte、 char
short sbyte 、byte、 ushort 、uint 、ulong 、char
ushort sbyte 、byte、 short、 char
int sbyte、byte、 short、 ushort、 uint、 ulong、 char
uint sbyte、byte、 short、 ushort、int、char
char sbyte、byte、 short
float sbyte、byte、 short、 ushort、int、uint 、long 、ulong 、char 、decimal
ulong sbyte、byte、 short、 ushort、int、uint 、long 、char
long sbyte、byte、 short、 ushort、int、uint 、ulong 、char
double sbyte、byte、 short、 ushort、int、uint 、ulong 、long、float、char、decimal
decimal sbyte、byte、 short、 ushort、int、uint 、ulong 、long、float、char、double

Convert转换

十、常量

const

  1. const int number=10;

十一、分支结构

if

  1. if(判断条件){
  2. 需要执行的代码;
  3. }

if-else

  1. if(判断条件){
  2. 需要执行的代码;
  3. }
  4. else{
  5. 需要执行的代码;
  6. }

if—— else if ——else

  1. if(判断条件){
  2. 需要执行的代码;
  3. }
  4. else if(判断条件){
  5. }
  6. else{
  7. 需要执行的代码;
  8. }

程序执行到 if 处,首先判断 if 所带的小括号中的判断条件是否成立,如果成立,就回一个 true,则执行 if 所带的大括号中的代码,执行完毕后,跳出 if-else 结构;如果不成立,返回一个 false,则跳过 if 语句后的大括号,执行 else 所带的大括号中的代码,执行完毕后,跳出 if-else 结构。

练习

用if — else if — else做一个简易的计算器

switch(结合enum)

  1. switch(变量或者表达式的值)
  2. {
  3. case 1
  4. 要执行的代码;
  5. break
  6. case 2
  7. 要执行的代码;
  8. break
  9. ...
  10. case N
  11. 要执行的代码;
  12. break
  13. default
  14. 要执行的代码;
  15. break
  16. }

练习

用switch做一个星期的判断

十二、循环结构

for

  1. for(初始表达式;条件表达式;增量表达式)
  2. {
  3. 循环体代码;
  4. }
  5. for(int i = 0;i<10,i++){
  6. }

初始表达式:声明循环变量,记录循环的次数;[ int i = 1 ]
条件表达式:循环的条件;[ i<=10 ]
增量表达式:改变循环条件的代码,使循环代码终有一天不再成立;[ i++ ]

练习

计算从1+2+….+100 (1+100)*100/2

while

  1. while(循环条件)
  2. {
  3. 循环体;
  4. }

首先判断 while 所带的小括号内的循环条件是否成立,
如果成立的话,也就是返回 true,则执行循环体;
执行完一遍循环体后,再次回到循环条件进行判断,如果依然成立,则继续执行循环体,如果不成立,则跳出 while 循环。

do-whlie

  1. do
  2. {
  3. 循环体;
  4. }while(循环条件)

首先会执行 do 中的循环体,执行完毕后,去判断 do-while 的循环条件,
如果成立则继续执行 do 中的循环体,如果不成立,则跳出 do-while 的循环体。
循环体中的代码最少会执行一次。

十三、break和continue

break

作用:立刻结束当前循环(不再进行这个循环)。

continue

作用:立刻结束本次循环(进行下一次循环)。

十四、数组、集合

数组

概念:数组是一个存储相同类型元素的固定大小的顺序集合。

作用:一次性存储多个相同类型的变量。

  1. int[] num = new int[]{1,2,3,4,5};

遍历

  1. foreach(数组数据类型 临时变量 in 数组名)
  2. {
  3. Console.WriteLine(临时变量);
  4. }
  5. foreach(var item in num){
  6. Console.WriteLine(item);
  7. }

冒泡排序

  1. int test = 0;//定义一个中间变量,用来交换值
  2. int[] arr = { 45, 1, 8, 2, 9, 89 };//定义一个无序数组,用来排序
  3. for (int i = 0; i < arr.Length-1; i++)//我们外层循环需要循环n-1次(1-5)
  4. {
  5. for (int j = 0; j < arr.Length-1-i; j++)
  6. {
  7. if (arr[j]>arr[j+1])//判断两个值大小是否要交换值
  8. {
  9. test = arr[j + 1];//如果数组第二个数小于前一个数,那么把第二个小的数先存放在 test中
  10. arr[j + 1] = arr[j];//把前一个大的数放到后面
  11. arr[j] = test;//再把我们存放在test中的小的数放到前面
  12. }
  13. }
  14. }

十五、值类型和引用类型

int 和 int[]的对比

C#基础详解教程 - 图2

十六、函数及其基本语法

函数的概念

一段特定功能的代码,有自己的名字,通过名字可以重复调用这段代码来帮我们完成特定的事情。

函数的声明(语法)

  1. static 返回值类型 函数名([形式参数])
  2. {
  3. 函数代码体;
  4. }

形参:

形式参数,在定义函数的时候,在参数列表中定义的参数。

实参:

实际参数,在调用函数的时候,传递给函数的具体参数。

返回值

关键字 return

①在函数中返回要返回的值;

②立即结束函数;

十七、函数的重载

在面向对象的语言中,允许我们在同一个类中定义多个方法名相同、参数列表(参数类型,参数个数)不同的方法,这样的形式我们称为方法重载。调用时编译器会根据实际传入参数的形式,选择与其匹配的方法执行。

十八、函数的高级参数

ref

1.作用
将一个变量传入一个函数中进行“处理”,“处理”完成后,再将“处理”后的
值带出函数。
2.要求
函数外必须为变量赋值,而函数内可以不赋值。
语法
形参和实参前面都要加 ref 关键字。
例如:A(ref num); static void A(ref int num)

out

一个函数中如果返回多个不同类型的值,就需要用到 out 参数。

形参和实参前面都要加 out 关键字。
例如:Number(a,b, out max, out min);

十九、递归

递归算法是一种直接或者间接调用自身函数或者方法的算法。(自己调用自己)
递归原则
①函数会一直调用自己,直到满足特定条件(递归要有一个结束条件);
②递归调用时会传递些参数,每次调用都会将一个新的参数传递给自己

二十、面向对象

●类是对一群具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用
●类就相当于制汽车是的图纸,是一个模板,是负责创建对象的

对象

●对象是由类创造出来的一个具体存在,可以直接使用
●由哪一个类创造出来的对象,就拥有在哪一个类中定义的属性和方法
●对象就相当于用图纸制造的汽车
在程序开发中, 应先有类,再有对象

类和对象的关系

●类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象
● 类只有一个, 而对象可以有很多个
●不同的对象之间属性的具体内容可能各不相同
●类中定义了什么属性和方法,对象中就有什么属性和方法,不可能多,也不可能少

字段

字段就是我们之前一直在用的变量。变量在面向对象的类中就叫做字段

属性

●特征被称为属性

●对对象的特征,描述通常可以定义 成属性。
●对象具有的行为通常可以定义为方法。注:方法般是动作即动词

封装

将对象的属性和行为封装起来,而将对象的属性和行为封装起来的载体就是类

继承

类与类之间同样具有关系,如一个百货公司类与销售员类相联系,类之间的这种关系被称为关联。关联是描述两个类之间的一般二元关系,例如,一个百货公司类与销售员类就是个关联, 学生类与教师类也是一一个关联。两个类之间的关系有很多种,继承是关联中的种。当处理一个问题时,可以将一些有用的类保留下来, 当遇到同样问题时拿来复用。由于鸽子属于鸟类,鸽子具有与鸟类相同的属性和行为。便可以在创建信鸽类时将鸟类拿来复用,并且保留鸟类具有的属性和行为。不过,并不是所有的鸟都有送信的习惯,因此还需要再添加一些信鸽具有的独特属性以及行为。鸽子类保留了鸟类的属性和行为,这样就节省了定义鸟和鸽子共同具有的属性和行为的时间,这就是继承的基本思想。可见软件的代码使用继承思想可以缩短软件开发的时间,复用那些已经定义好的类可以提高系统性能,减少系统在使用过程中出现错误的几率。继承性主要利用特定对象之间的共有属性。例如,平行四边形是四边形(正方形、矩形也都是四边形),平行四边形与四边形具有共同特性,就是拥有4个边,可以将平行四边形类看作四边形的延伸,平行四边形复用了四边形的属性和行为,同时添加了平行四边形独有的属性和行为,如平行四边形的对边平行且相等。这里可以将平行四边形类看作是从四边形类中继承的。在C#语言中将类似于平行四边形的类称为子类,将类似于四边形的类称为父类。值得注意的是,可以说平行四边形是特殊的四边形,但不能说四边形是平行四边形,也就是说子类的实例都是父类的实例,但不能说父类的实例是子类的实例。

多态

了解了父类和子类,其实将父类对象应用于子类的特征就是多态。依然以图形类来说明多态,每个图形都拥有绘制自己的能力,这个能力可以看作是该类具有的行为,如果将子类的对象统一看作是父类的实例对象, 这样当绘制任何图形时,可以简单地调用父类也就是图形类绘制图形的方法即可绘制任何图形,这就是多态最基本的思想。多态性允许以统的风格编写程序, 以处理种类繁多的已存在的类以及相关类。 该统-风格可以由父类来实现,根据父类统风格的处理, 就可以实例化子类的对象。由于整个事件的处理都只依赖于父类的方法,所以日后只要维护和调整父类的方法即可,这样就降低了维护的难度,节省了时间。在提到多态的同时,不得不提到抽象类和接口,因为多态的实现并不依赖具体类,而是依赖于抽象类和接口。
再回到绘制图形的实例上来。作为所有图形的父类图形类,它具有绘制图形的能力,这个方法可以称为“绘制图形”,但如果要执行这个“绘制图形”的命令,没有人知道应该画什么样的图形,并且如果要在图形类中抽象出一一个图形对象,没有人能说清这个图形究竟是什么图形,所以使用“抽象”这个词汇来描述图形类比较恰当。在C#语言中称这样的类为抽象类,抽象类不能实例化对象。在多态的机制中,父类通常会被定义为抽象类,在抽象类中给出一个方法的标准,而不给出实现的具体流程。实质上这个方法也是抽象的,如图形类中的“绘制图形”方法只提供个可以绘制图形的标准,并没有提供具体绘制图形的流程,因为没有人知道究竞需要绘制什么形状的图形。在多态的机制中,比抽象类更为方便的方式是将抽象类定义为接口。由抽象方法组成的集合就是接口。接口的概念在现实中也极为常见,如从不同的五金商店买来螺丝帽和螺丝钉,螺丝帽很轻松地就可以拧在螺丝钉上,可能螺丝帽和螺丝钉的厂家不同,但这两个物品可以很轻易地组合在一起,这是因为生产螺丝帽和螺丝钉的厂家都遵循着一一个标准 ,这个标准在C#中就是接口。依然拿“绘制图形”来说明,可以将“绘制图形”作为- -个接口的抽象方法,然后使图形类实现这个接口,同时实现“绘制图形”这个抽象方法,当三角形类需要绘制时,就可以继承图形类,重写其中的“绘制图形”方法,并改写这个方法为“绘制三角形”,这样就可以通过这个标准绘制不同的图形。

二十一、控制台实战

学生管理系统