零基础入门-C#实用编程
目录
1. 基础入门
1.1 演示用开发工具
1.2 C#程序结构说明
1.3 基础数据类型与运算符
1.4 输入输出
1.5 第一个C#程序
2 基础数据结构
2.1 什么是数据结构
2.2 C#常用的数据结构
2.3 数组Array
2.4 链表List
2.5 队列Queue
2.6 栈Stack
2.7 哈希集HashSet
2.8 字典 Dictionary
2.9 判断语句
2.10 常用循环语句
3 面向对象编程
3.1 什么是对象
3.2 类型 Class
3.3 接口与父类
3.4 接口
3.5 父类
3.6 泛型
基础入门
开发工具讲解
开发工具:Microsoft Visual Studio
教材演示版本:VS 2019 社区版
软件下载地址:https://visualstudio.microsoft.com/zh-hans/vs/
C#程序结构说明
程序,由若干语句组成,包含在代码块 {} 花括号内部。
比如以下程序,共有4条语句,绿色部分为注释说明(每一行开头带有//)
程序语句:由关键字、变量名称、运算符、语句结束标识符号组成。
主要分为:声明语句、赋值语句、函数语句、条件语句、循环语句
赋值语句:全部带有赋值号“=”
涉及到的关键字有:
类型关键字:char、int、double、string、DateTime
赋值号 =
语句结束标志,半角分号 ;
声明语句: 不带赋值号
函数语句:带括号
比如案例中:
DateTime.Parse就是一个函数
传入参数是一个字符串: "2020-11-20"
运算结果保存到:日期变量
条件语句和分支语句:关键字if、else 、 switch
条件语句 if示例
分支语句 switch示例
循环语句示例
基础数据类型与运算符
基础数据类型
数值型:int、double、float(不常用)、byte(字节)、decimal(用于高精度计算,比如货币计算)
布尔型:bool 用于保存 true(是)、false(否),用于条件判断
字符型:char
字符串:string
日期:DateTime
常用运算符
算数运算符
加+ : int a = 1+1; //结果 a 保存 2
减- : int a=2-1; //结果 a 保存 1
乘* : int a=2*2; //结果 a 保存 4
除/ : int a=6/3; //结果 a 保存 2
模% : int a=5%3; //结果 a 保存 2
条件判断:等于 == 不等于 !=
大于 > 小于 <
大于等于 >= 小于等于 <=
括号:()
bool a = (3*2) > 4; // 6大于4, a 保存 true;
放在条件语句里面 if (a) 或 if (6 > 4)
输入输出
函数是最小的程序;
比如上例:
代码定义了一个Main 函数,static 表示静态,void 表示函数没有输出值,
括号内部string[] args 表示输入值是一个 string类型的数组,类型+中括号[] 表示某类型的数组。
取三点定位算法部分代码作为例子:
输入值是:f:频率,hr:UE高度,ht:接收到基站的有效高度
输出值是:return 返回的一个double类型计算结果。
注:
return 是作为函数返回的关键字,函数A返回的是一个double类型。
假如函数声明为 string A() 则函数A返回的是一个string类型,括号内没有参数,所以没有输入值。
第一个C#程序
以下是小学6年级期末考的试题,请选择任意一道题,完成程序设计。
需求如下:
试题答案:
需求分析示例:
原始需求
根据需求所述,程序的输入参数分别为:学生总数、男女比例。参数的数据类型为整数的int类型。
程序目的是得出男生,女生各有多少人。
可实现代码如下:
运行结果:
参考答案解析:
函数Example的返回值采用的是4.7.2框架的新特性,返回值的类型是元组。
函数ExampleOld的输入值包含了两个out关键字,作用是将“男生数量”和“女生数量”标记为外部变量,使得计算结果可以被外部读取。
基础数据结构与算法实现
什么是数据结构
百度释义
可见,一个优秀的数据结构有利于提高算法的运行效率
C#常用的数据结构
数组Array
使用方法,以整形数组为例:
注:++i 表示的是 i = i+1
链表List
一般使用List<T>,尖括号<T>代表着泛型的名称叫做T,泛型后面会讲到,这里重点关注List的使用。
List的使用方法和Array类似,都可以用索引器“中括号[]”进行取值。
List跟Array的主要不同点如下:
List长度是动态的,可以使用Add和Append对List的元素进行追加。
Array长度是固定的。
代码示例:
注:++i 表示的是 i = i+1
队列Queue
队列,简单可以想象成一个流水线,特点是先进先出。
一般使用Queue<T>,代码示例:
栈Stack
栈,可以想象成一个子弹夹,第一发子弹总是最后压进去的,特点是后进先出,
所以C#的栈类型,压栈的函数叫做Push。
代码示例:
哈希集HashSet
用法参考List,主要用于消除链表或数组中的重复数据。
字典 Dictionary
可以把字典理解为“键值对”,字典中所有键都有对应的值,而且每一个键都不重复。
用法参考List,代码示例:
判断语句
条件语句 if示例
分支语句 switch示例
常用循环语句
面向对象编程
软件工程经历了四次演变。
第一次演变形成了高级语言,C#也属于高级语言的一种,使得程序员可以轻松编写代码。
第二次演变形成了结构化程序设计,面向复杂程序逻辑,提出了“自顶向下,逐步细化”的指导思想。
第三次演变出现了面向对象程序设计,有了结构化程序设计,虽然逻辑复杂度降低了,但是随着业务需求的发展,软件扩展困难的现象促进了面向对象的发展。
第四次演变出现了软件架构,并且创造了“组件”的概念。
面向对象程序,所有的业务都是由对象来完成的。
比如:List类就有一个Sort进行排序,Sort是List面向使用者的一个可调用的方法,Sort的实现细节包含在List内部,对外不可见。
什么是对象
对象的英文名称为object,代表着一切存在的事物 。在 C#程序中, object 是所有类型的父类(也包括基础类型int, double 等)。
作用:
将事物的属性和行为封装成一个具体的类型,降低对事物分析和代码复用的复杂度。
身边各种面向对象的方法:
手机游戏:角色各种属性(姓名,血槽, 能量等),技能(跑动, 跳跃)
微信用户:用户最重要的数据(手机号码, 密码)
可以想到的还有很多。
类型 Class
声明方式
class 类型名称{
}
比如:创建一个Console控制台应用程序的时候,工程内部会默认有一个Program类型
使用方式:类型的创建需要使用new 语句, 可以参考前面List,Queue等数据结构的创建过程,传入适当的参数进行对象创建。
访问权限关键字:
public 公开:外部可以访问到
protected 保护:继承的子类可以访问到
private 私有:只有当前类型才能访问到
默认:只有当前命名空间的成员能访问到
构造函数:用于为当前类型创建对象,可以理解为初始化。默认构造函数为:类名+括号,例如:
上例中,public Class1() 就是当前的构造函数,带有 get set 访问器的是属性,不带有get set 访问器的是变量。
接口与父类
接口
接口用于规定类型必须产生的行为,就如同协议,举例如下:
有一个接口 IStudent,(接口命名一般前面加个大写的I),代码如下:
它定义了学生应该做到“好好学习,天天向上”
目前学校有三类学生,分别是“高中生”、“初中生”、“小学生”,它们三类学生的学习内容和具体要求都不一样,于是有如下定义:
然后我们定义学校,里面有个两个行为,招生和开学
于是当学校招生的时候,就会变成如下:
所有符合IStudent接口的类型都可以通过招生函数。
此外,不符合IStudent接口的类型,编译就不会通过。
父类
父类用于定义类型主体具备的属性和基本行为,我们将前面学校招生的问题细化。
abstract 表示抽象类,只能被继承作为父类,不可以通过new进行创建。
上述定义了学生这个主体定义了GoodLearning行为的基础要求,要求好好学习就必须“听课、看书、做作业、考试”,并且virtual关键字允许了继承当前父类的子类可以对“听课、看书、做作业、考试”的具体行为自定义。
示例代码如下:
注意:每一个可重写函数,子类的override函数 对应着父类的一个virtual函数
下面,同样对学校的招生函数进行优化,明确了招生目标不仅仅要有学习的行为,而且必须是一名学生,于是把传入招生函数的参数类型改为“学生”
代码示例如下:
再进一步,对学校进行分类,我们定义一个小学的类型,它继承学校这个父类。
小学新追加了特色:只能招小学生。
代码如下:
经过前面的优化,我们实例化小学这个类型进行招生,如下:
总结
接口定义了面向对象的行为规范,父类提供了类型的基本属性和基础行为,利用接口和父类的技术使得面向同一种问题提供了不同的实现方案。
涉及到的关键字:
new interface abstract class as virtual override public protected private
泛型
先看一个案例:
此处,只有一个List类型,却产生了stringList 、intList、doubleList、charList 多种应用,它并不是为不同类型逐个实现链表,而是采用了泛型技术提高了代码的复用程度。
下面看泛型怎么实现,继续优化我们的学校。
上面代码多出了“尖括号StudentType”,这就是泛型定义,并且“where StudentType : 学生”,指定了当前这个StudentType必须是继承“学生”的类型。
于是对于小学,我们不需要单独写一个小学类型了。