0%

金老师C#课

一.大致了解C#基本编程规则
1.1 基本规则
“标识符(identifier:即程序中拥有特殊含义的单词)”区分大小写
每条语句以分号结尾,多条语句可以使用”{}”组合为一个语句块
编写的代码放在”类(class)”中,类是C#编程的基本单元
存放C#类的源代码文件其扩展名为”.cs”,一个”.cs”文件中可以存放多个C#类
1.2 Visual Studio中文件的组织方式:
“项目(Project)”是Visual Studio编译的最小单元
一个”解决方案(solution)”中可以有多个项目,显示为粗体的是启动项目
一个项目中可以有多个类文件。一个类只有被包括在一个项目中,才可以被Visual Studio编译
程序入口点是Program类中的Main()方法
1.3 为什么要学习面向对象程序设计
面向对象是一种主流的软件开发与设计方法
当前各种软件系统,基本都是应用面向对象思想与计算开发出来的
1.4 软件是如何编写的
面临问题 做出决策
如何设计与选中特定的算法处理信息 可以选择已有的算法,也可以设计新的算法
算法:分而治之,动态规划
程序控制结构:分支,循环,递归
如何表达以方便计算机处理 设计和选用合适的数据结构
如何编写程序实现算法 选择合适的技术手段,设计合理的技术方案。软件系统价格,面向对象的分析与设计,编程语言,开发框架,软件平台…
1.5 需要掌握基础知识
程序如何被计算机执行–>各种信息是如何用0/1表达的–>计算机是由哪些元件组成,工作原理是什么–>操作系统如何启动一个程序的执行

如何编写可以执行的程序–>第一步:编写源代码–>第二步:编译–>第三步:得到可执行的程序

增压构造求解问题的算法–>分析问题–>设计算法–>编写程序

二.程序是如何被计算机执行的
2.1 计算机能直接执行由0和1构成的机器指令
计算机中数值信息,直接用二进制”0”和”1”表达,非数值信息,采用”编码”的手段

“门”是这样的一种电路:它规定各个输入信号之间满足某种逻辑关系时,才有信号输出,通常有下列三种门电路:与门、或门、非门(反相器)。从逻辑关系看,门电路的输入端或输出端只有两种状态,无信号以“0”表示,有信号以“1”表示。

以”0”和”1”表达的指令,可以由计算机硬件直接执行,因此,将它们称为”机器指令”
不同体系结构的计算机硬件,能执行的机器指令是不一样的,每种机器能执行的所有机器指令,称为这种机器的”指令集”
2.2 计算机的大脑——CPU
CPU可以执行机器指令(“0”和”1”)
指令与数据通常保存在文件中
指令&数据->可执行程序文件(.exe)

Win平台下可执行文件通常以.exe结尾,另一种扩展名为.dll(动态链接库)需要被.exe装入后才能执行

2.3 外部存储器 & Memory(内存)与内存条
各种程序平常保存在外部存储器中
如硬盘,U盘等
放在外部存储器中的程序并不能直接允许,需要被装入内存后,才能执行
内存条中的存储新品包容许多存储单元,用于保存程序指令和数据
存储单元的集合,称为”内存”
001011…
011010…
101011…
内存存储数据—>分为指令,指令使用的数据

可执行程序.exe文件保存在外部存储器

在计算机上双击,系统读取文件,把它包容的指令和数据装载到内存

CPU直接存取放在内存存储单元的数据,并负责执行这些指令
2.4 区分两种不同的内存类型
物理内存
计算机上的物理芯片

虚拟内存
操作系统所提供的”虚拟内存”

C#写的.NET程序,无法直接访问物理内存上的特定数据单元,它所访问的上由操作系统负责提供的”虚拟内存”

2.5 程序开发与运行过程简述
软件工程师用各种编程语言写计算机程序

编译器把源程序转换为二进制指令与数据,以文件方式保存在外部存储器中

操作系统将程序文件从外部存储器读入到内存中

CPU从内存中取出指令执行
三.Dot Net运行原理
3.1 “编译”是怎么回事
纯文本形式的源代码
⬇提交
C#编译器编译源码
⬇生成
二进制形式的可执行程序文件(HelloWorld.exe)

1
2
3
4
5
6
7
8
9
10
11
12
13
using System;//表示将使用.Net基类库中的System命名空间

public class Program//类名Program
{
//程序入口点Main(数组[] 参数名)
static void Main(string[] args)
{
Console.WriteLine("Hello,World");
}
}
//保存为ANSI格式(源代码标准格式)
//helloworld.cs
csc helloworld.cs

Microsoft (R) Visual C# Compiler version 3.5.0-beta4-20121-02 (00d6c926)
Copyright (C) Microsoft Corporation. All rights reserved.

“编译(compile)”,粗略地说,它负责把人编写的源代码”翻译”为计算机可以识别并执行的二进制代码

3.2 可执行程序也是分类的
可执行程序也分很多类型,在Windows平台下,可分为
可执行程序
⬇ ⬇
托管程序 非托管程序
例如:使用C#,VB.NET编写的可执行程序,运行时要求目标计算机上必须安装有.NET Framework 例如:使用C/C++编写的可执行程序,可以不需要安装额外软件,就能直接在操作系统中运行
3.3 “托管的”应用程序是什么意思
.NET应用程序是”托管(Managed)”的,意思是它必须在一个独立的运行环境(即CLR)中运行,并收到这个运行环境的管理与控制

.NET应用程序
⬆管理
.NET虚拟机(CLR)
CLR:通用语言运行时.NET应用程序的运行环境,可以看成是一台专用于运行.NET应用程序的虚拟机(Virtual Machine)
⬇调用功能
操作系统(Windows)
⬇管理
构成计算机的各种硬件
3.4 .NET程序的开发与运行”全景图”

image

四.怎样构造求解问题的算法
4.1 什么是”算法(algorithm)”
计算机中的算法,主要是指为了解决某个问题而设计的一种解决方案,包容一系列计算机能够执行的有着特定顺序的命令,计算机执行完这些命令,将得到某种结果,意味着某个问题已经有了一个结论

算法的针对性很强,专用于解决特定的问题
算法的设计,通常与数学有很密切的联系,并且是独立于特定的编程语言和软件平台的,这就是说:
可以使用多种编程语言,以多种方式,在不同的平台上实现同一个算法

4.2 从”结构化”到”面向对象”
程序是一个”黑盒”,程序=数据结构+算法
程序设计可以看成是一种”抽象”的艺术
使用”抽象”的思维方式,构造软件系统的顶层模型
4.2.1 数据结构————对数据进行抽象
先确定一种数据结构,如何基于此数据结构设计算法
在程序设计中,依据要解决的特定问题,分析它所设计的相关数据和其中蕴含的各种信息,安装特定编程语言所制成的语法特性,将它们转换为特定的数据结构,往往是整个开发中至关重要的一步
4.2.2 基于数据结构确定算法
将人的计算方法转换为计算机算法,每个算法用一个函数实现
算法就是一系列的命令,计算机通过执行这些命令,完成特定的数据处理工作
4.2.3 进一步细化与调整设计方案
4.2.4 最终的技术设计方案
“由粗略到详细”,”从上层到下层”地逐层设计
4.2.5 确定开发顺序的基本方法
具体开发时,”从 下层 到 上层”地逐层开发,像盖楼一样
开发被别人调用,自己不用调用别人的函数

开发中间层函数,它需要调用底层已经实现好的函数

开发顶层函数,它需要调用中间层已经实现好的函数,通常情况下,避免跨层调用
点击展开结构化代码
4.3 转为面向对象实现
给函数搬一个家–类

重大变化:
1)DateCalculator这个类的职责很明确,它负责”计算日期”,除此之外什么都不做
2)外界只能”看到”并调用它所定义的唯一一个”公有(public)“方法
CalculateDaysOfTwoDate(),根本家不知道它内部定义是什么样的

面向对象带来的好处:
1)从使用者角度,DateCalculator类因为”简单“,所以”易用“
2)具体计算日期的算法被封装道理DateCalculator类的内部,在必要时可以修改算法,外部调用者不会收到影响,其调用代码不需要改变

点击展开面向对象代码
4.4 使用内置库实现
从如下事例中,可以看到,如果有一个功能强大的组家奴,基于这些组件开发应用程序,可以大大提升软件开发效率,因为可以重用别人的工作,不需要从头开始
即不要重复发明轮子,尽量重用别人的代码

点击展开内置库代码
五.变量、数据类型和表达式
5.1 什么是”变量”
程序运行所需要处理的数据,通常都要放到”变量(variable)”中
变量可以看作是一种数据容器
不同类型的”容器”,适合放置不同类型的数据,这种”类型”,称为”变量的数据类型“
5.1.1 如何在C#中定义变量
语法格式:
数据类型名称 变量名 = 变量初始值;
示例
int value = 100;
该语句定义了一个int(整型) 变量,可以放整数 ,初始值为100,最后以”分号结束,C#语句结束不能省略分号”
5.1.2 变量存储与内存中
内存由多个内存单元构成,每个内存单元都有一个编号,称为”内存地址“
给定一个”内存地址”,就能找到特定的内存单元
计算机可以从内存单元中写入或读出数据
使用比较底层的编程语言,如”汇编语言(Assembly Language)“,可以直接指定地址去存取特定的内存单元,但是由于硬件或系统不同,都可能需要修改程序,因此会低效

解决方案
1)应用程序需要读取存取数据时,不指定具体的内存地址,只给出一个”名字”,这个”名字”引用某块内存区域
2)这个”名字”具体引用哪块内存区域,由OS安排,应用程序不进行管理
3)应用程序只需要指定可以按照”名字”找到并读写区域即可
这个内存区域的”名字”,结束所讲的”变量”

5.1.3 通过变量名”间接”地存取内存
变量的名字,可以看出是特定内存区域的”别名”,通过它计算机就能找到特定的内存单元存取数据
有了变量名,将不再需要显示指定一长串地址数值来访问内存单元了
5.1.4 什么是”给变量赋值”
变量定义好后,可以通过赋值语句给他传不同的值

语法格式:
变量名=变量新值;
给变量赋值,其实就是找到变量所代表的内存区域,把指定的数值写入其中

注意:写入到内存单元中的数据,都被转换为二进制数值,计算机并不能直接处理十进制数

5.1.5 什么是变量间的相互赋值
变量间的相互赋值,本质上是内存单元间的值赋值
不同变量直接相互赋值,虽然值一样,但是变量却是相互独立的,不会因赋值而同步变化
5.2 C#语言数据类型
C#语言内置数据类型 编译时转变为CLR CLR支持的基础数据类型
int <—> System.Int32
long <—> System.Int64
float <—> System.Single
Double <—> System.Double
点我展开示例代码
5.2.1 从内存模型角度,C#变量可分为以下两种类型
C#数据类型
值类型
int 值类型变量存活与”线程堆栈”中
double

引用类型
string 引用类型所引用的对象,生存与”堆”中

5.3 运算符与表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
namespace Lesson_04_Operators_and_expressions
{
internal class Program
{
public static void Main(string[] args)
{
UseOperator();
UseExpression();
} #region "运算符与表达式"

///<summary>
///使用运算符
/// </summary>
static void UseOperator()
{
//+-*/,()
double result = ((5 + 3) * 2 - 7) / 6d;
Console.WriteLine(result);

int value = 9 % 4;
Console.WriteLine(value);

int index = 1;

//index++ <==> index=index+1
Console.WriteLine(index++);
Console.WriteLine(++index);
}

///<summary>
///使用表达式
/// </summary>
static void UseExpression()
{
int value = 100;
Console.WriteLine(value*2);
}
#endregion
}

}
5.4 选择结构与逻辑表达式
三种典型的程序代码执行流程
顺序执行
按条件选择一条分支执行 <====> 选择结构
在特定场景中反复执行特定语句 <====> 循环结构
程序流程图
在结构化程序设计中,经常使用一种称为”程序流程图“的示意图来表示程序的执行流程

使用if/else语句实现程序中的选择结构
语法:

1
2
3
4
5
6
7
if(条件 == true)
{
//执行语句A
}else
{
//执行语句B
}

使用逻辑表达式表达条件,”==”是逻辑判断运算符

逻辑表达式通常用于表示某种条件是否得到满足
当程序运行时,计算机解析逻辑表达式,会得到一个值,在C#中,这个值只有”true”或”false”
在if语句中,基于逻辑表达式执行的结构执行特定的分支
用于构建逻辑表达式的运算符
运算符 说明

1
2
3
4
5
6
7
>	大于
< 小于
== 等于
>= 大于等于
<= 小于等于
!= 不等于
注意:=>不是”等于大于”,而是Lambda表达式