C#基础入门
c#是什么?
c#是由微软公司在2006年发布的一种全新的 、简单的 、安全的 、面向对象 的高级编程语言。
问题:c#能做什么?
c#可以做桌面应用开发 、服务器开发 、移动应用开发 、游戏开发 、人工智能开发 、各类工具开发; 目前应用最广泛的就是互联网系统和游戏。
初识
操作系统
操作系统(Operation System,OS)是指控制和管理整个计算机系统的硬件和软件资源 ,并合理的组织和调度及调度计算机的工作和资源分配,以提供给用户和其它软件方便的接口和环境。
常见的操作系统:windows、Linux、Mac OS X、android、ios
计算机的机器语言构成
0、1的指令集合
c#执行在计算机上的原理是什么
由高级语言,经过编译的过程翻译成计算机底层可以识别的0、1指令
程序如何与硬件交互
运行在操作系统之上,通过系统统一管理硬件资源
编程语言分类
-
编译型语言:C++ / C
-
解释型语言:JavaScript / Phthon / PHP
-
半编译半解释型语言:Java / C#
CLR介绍
通用语言运行平台(Commom Language Runtime,简称CLR)是微软为他们的 .Net虚拟机 所选用的名称。这是通用语言架构 (简称CLI)的微软实现版本,它定义了一个代码运行环境。
JIT -即时编译系统
- 预先编译:提前把代码编译成机器码
- 动态编译:对源代码一句一句,边翻译边运行
即时编译:运行时,一句一句边翻译边运行,如果翻译的代码属于*热点(HotPot)*那么就会进行缓存,本次运行过程中,如果再遇到本代码段,可以直接使用;直到程序退出。
所以兼容了二者的优点
.Net介绍
什么是.Net平台
.Net读作"dot net"
.Net平台是C#语言从编写到运行所依赖的环境 ,其上也构建多种多样的应用开发工具及类库 ;包括了一个虚拟运行时的CLR ,以及一系列的类库。
C#基础语法
语句注释
语句:C#程序由一系列语句组成,一个语句就是一条指令,分好结尾;
- 语句顺序执行
- 语句每一条都会区分大小写
注释:注释(Comments)并不是一种C#代码,而是对代码的说明文字,方便自己或他人查看从而理解程序的含义
- 单行注释://注释内容,只可写一行
- 多行注释:/* */
字面量
字面量就是计算机程序用来处理数据,字面量规定了:数据在程序中的书写格式。
变量
变量是用来存储一个数据的内存区域 ,里面存储的数据可以变化。
内存可以理解为一系列的空着的房间。
变量为什么需要类型
- 任何一个程序中的变量,程序员都需要声明其变量的数据类型。
- 不同应用场景下,需要存储的空间大小不同,比如存储成绩(0-100)跟存储银行款(上万亿)。
变量定义格式
数据类型 变量名称 = 初始值;
c#
int score = 10;
变量的读和写
- 从变量代表内存中,把数据取出来使用,叫做读取;
- 把数值放进变量所代表的内存中,叫做写入;即改变了变量的值;
关键字、标识符
C#中,会保留一些单词作为特殊含义,拥有特殊功能,例如:int、double、float、public、class...
关键字不可作为变量的名称来使用;
什么是标识符
C#中,用于给变量、类、方法等用户自定义元素起名的符号串,即标识符;
变量命名规则
- 变量名第一个字符必须是字母、下划线(_)或者@符号
- 后续字符可以是字母/数字/下划线
- 不可以使用C#内的关键字,比如int
变量命名指导规范
- 尽量使用明确的单词或者单词缩写,建议全英文
- 使用驼峰命名法
变量使用细节
- 变量必须先声明再使用
- 变量必须存储跟类型匹配的数据
- 变量定义可以没有初始值,使用必须有初始值
- 一条语句可以定义多个变量
- 变量有效范围是从定义开始,一直到遇到一个"}"截止,同一个范围内变量名不可重复
进制与转换
什么是二进制
二进制数(binaries)是逢2进位的进位制,0、1是基本算符;
十进制:0 1 2 3 4 5 6 7 8 9(进位)10 11 ......
十进制转二进制算法
除二取余法
二进制转十进制算法
按位求幂相加
八进制
八进制数是逢8进位的进位制 ,0-7是基本算符;
十六进制
C#中也可以使用十六进制对数据进行表达,逢16进位,所以需要16个 个位数字 表达方法。
0 1 2 3 4 5 6 7 8 9 A(10) B(11) C(12) D(13) E(14) F(15) 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
C#中的进制表示
二进制:
c#
int n1 = 0B101;
十六进制
c#
int n2 = 0x1A;
八进制在c#中没有明确的表达方法;
变量的基础原理
内存单位
- 内存中可见的最小单位是bit(比特),表示0和1
- 内存中用于存储数据的最小单位是8个bit,即1byte(字节)
变量内存分配案列
变量生成的时候,系统会分配给其一块大小合适的内存;
字符的表示
一个字符可以是普通的英文字母,一个汉字、一个符号,占有2byte的内存大小。
字符的本质
自然语言可以理解'A',计算机只能看到2byte的数字;
对于任何一个2byte的数字,如果是char则理解为字符,否则理解为数字;
建立某一个数字 与某一个字符 之间联系的方法,即为编码;
UTF-16码表举例(十六进制)
数据类型
C#中将数据类型分为两类
- 值类型
- 引用类型
基础值类型
- 整数
- byte
- short
- int
- long
- 浮点数
- float
- double
- 字符
- chart
- 布尔
- bool
变量数值类型(整数)
数值类型选择,一般选int,int装不下选long。默认为int
s表示signed,即有符号;u表示unsigned,即无符号;
大空间变量,可以接受小空间变量的赋值,反之则不可;
变量数值类型(浮点数)
变量数值类型(字符与布尔)
常量
什么是左值/右值
- 左值:可放在等号左边 的存储单元,即用户可以读取 并可以改变其存储的值;
- 右值:可以放在等号右边 的存储单元、字面量,即用户可以读取的存储的单元或者值
什么是常量
- 常量包括字面量 以及常变量 ,程序执行期间不会改变,常量在语句中只能作为右值的存在,不能作为左值。
- 常变量也是一种变量
- 定义期间必须给定初始值,否则vs会报编译的语法错误
- 定义后,只能读取访问,不能改变其值
- 常变量定义使用关键字const,格式如下
- const 变量类型 变量名 = 初始值;
常变量的作用
- 可以作为字面量的载体,一次性修改多处数值
- 防止定义初始值后,被其他程序员修改
整数二进制的存储原理
研究Byte类型
为什么一个byte类型的整数取值范围是0-255?
因为当8个bit都是1的时候,对应的是进制就是255;
那么,为什么一个sbyte类型的整数取值范围是-128-127呢?
此时就需要探究下整数在内存中导读如何存储为二进制!
二进制内存最高位1bit便是符号,其它位表示数值绝对值;
缺点:无法正确处理数据运算
方案三 补码
补码的优势
回顾问题:
sbyte的取值范围
检测Overflow
c#
sbyte b = 127
checked{
b++;
}
//如果溢出,则vs会编译报错
浮点数二进制存储方法
浮点数
常用浮点数分为float 和double ,二者都可以表达带有小数点的数字,分别占4字节 和8字节。
问题:
- 带小数的量为什么称为浮点数
- 浮点数在内存中的二进制是如何存储的
小数二进制表达:乘二取整法
十进制消暑转二进制表示,采用乘二取整法
二进制小数转化为十进制
二进制小数转化为十进制表示,采用按位符术次幂,相乘再相加
浮点数十进制转二进制
- 一个完整的浮点数:整数.小数,转化为二进制
- 整数部分除二取余法得到二进制
- 小数部分乘二取整法得到二进制
- 整数在前,小数在后,用小数点相连
科学计数法(十进制)
科学记数法是一种数字的表示方法。把一个数表示成 x 与 10的n次幂相乘的形式
二进制的科学计数法
二进制科学计数法是一种数字表示的方法。把一个数表示成 x(二进制) 与 2的n次幂相乘的形式
浮点数的存储(float)
尾数规则
尾数必须以 1.xxx 的形式进行表示,即整数部分必须是1
指数规则
指数必须加上127 的偏移量(Bias),得到的数据转化为二进制,存储在指数区域;这种方式称为移码存储。
为什么不用补码呢?主要是便于大小比较以及电路设计。
移码存储细节与对阶
对阶操作:对操作两个浮点数相加的时候,需要把二者的指数调节一致才能计算
对阶操作举例
注意
c#面向过程
运算符和表达式
- 运算符:对字面量或者变量进行操作的符号
- 表达式:用运算符把一个或者多个字面量或者变量 连接起来符合语法的式字即表达式
c#
int a = 10;
int b = 20;
int c = a + b;
- +:运算符
- a+b:是表达式,且由于+表示的为算术运算符,所以称为算术表达式。
运算符种类
- 算术运算符
- 位运算符
- 赋值运算符
- 逻辑运算符
- 关系运算符
算术运算符
注意
- 整数与整数操作,结果是整数
- 整数与浮点数操作,结果是浮点数
- 浮点数与浮点数操作,结果是浮点数
自增自减运算符
隐式类型转换
把一个取值范围小 的数值或者变量,赋值给另一个取值范围大的变量
隐式转化规则
- 无符号 不能接纳有符号的数据
c#
sbyte b = 10;
uint num = b; //报错
- 数据之间的隐式转化关系如下
运算过程中隐式转换
- 取值范围小的数据,与取值范围大的数据进行运算,小数据数据提升为大类型后,在进行运算;
- byte short chart 三种数据在运算的时候,都会首先转化为int类型
显式类型转化
- 把一个取值范围大 的数值或变量,赋值给另一个取值范围小的变量
不可直接赋值,需要强制类型转换
格式:目标数据类型 变量名 = (目标数据类型)需要转换的数据或者变量;
c#
// long a = 10;
// int b = a;//报错
// long a = 10;
// int b = (int)a;
float a = 10.1f;
int b = (int)a;//精度损失
数据截断与歧义
- 如果大整数类型给到小整数类型,数据有可能被截断 或者歧义。
显示类型转换-更灵活的版本
- Convert 是C#提供的类(类似于console)。里面含有一系列类型转换的功能方法
- 特点:任意数据类型 的值转换为任意数据类型
- 数据类型无法转换时,会报错
位运算符
位运算(1bit)
-
在计算机内部,每个数据都是0、1排列组成,本质存储二进制bit;按bit为进行的运算,称为位运算
-
& 与运算: 两者都为1,结果为1
- | 或运算: 两者有一个为1,结果为1
- ^ 异或运算: 二者不同结果为1
- ~取反运算:0变1,1变0
真值表
位运算(整数)
- 整数由多个bit组成,也可以进行按位运算
左移或右移位运算
- 构成整数的bit们,可以集体向左或者向右移动
- 左移n位,原来的数字需要乘以 2 的 n 次方
- 右移n位,原来的数字需要乘以 2 的 -n 次方
练习
关系运算符与逻辑运算符
关系运算符
- 关系运算符:用于判断两个数据之间的大/小/相等关系 的运算符。运算结果为bool类型,即true 或者false。
- c#的逻辑运算符无法赋值给整数,整数也无法复制给bool变量
c#
int a = 10,b = 20;
bool flag1 = a > b;//false
bool flag2 = a < b; //true
关系运算符汇总表
三元运算符
语法格式:判断条件?条件1:条件2
-
作用:
- 计算判断条件的真假
- 如果是真,则表达式结果为值1
- 如果是假,则表达式结果为2
赋值运算符与sizeof
赋值操作用于给一个变量装入数值
其它运算符
运算符的优先级
优先级的概念
- 在一个表达式中,存在多个运算符的时候,需要规定计算的先后顺序 ,即优先级
举例
c#
int a = 1,b=2,c=3,d=4;
int r = a + b * c / d;
- +-优先级相同
-
- /优先级相同,且高于+ -
- 优先级相同,从左到右
- 自增自减(++/--),优先级高于四则运算
⚠️ 优先级并不是先运算,而是先结合为整体
关系逻辑运算符优先级
- !> 算数运算符 > 关系运算符 > && > || > 赋值运算符
括号优先级
- 在一个表达式中,如果有括号,先运算括号内的表达式
优先级表(部分)
⚠️ 如果害怕顺序出现问题,把需要进行的每一步运算都用括号包裹
变量键盘输入
变量输入输出
输入
c#
Console.Read(); //读入一个字符,得到其Unicode值
Console.ReadLine();//读入一个字符串
举例
输出
c#
Console.Write(); //输出字符
string a = "我";
string b = "你";
Console.WriteLine("{0}爱{1},a,b);//输出字符串 我爱你
语句 循环
if语句
格式
if(判断条件1){
语句代码;
}else if(判断条件2){
语句代码;
}else if(判断条件3){
语句代码;
}else if(判断条件4){
语句代码;
}
......
else{
语句代码;
}
switth语句
格式
switch(条件表达式){
case 值1: 语句代码; break;
case 值2: 语句代码; break;
case 值3: 语句代码; break;
......
default: 语句代码; break;
}
while 循环语句
格式
while(条件判断语句){
循环体语句;
条件控制语句;
}
概念:条件语句成立,则执行循环体语句
⚠️ 条件判断语句设为ture设置死循环
do while循环
格式
do{
循环体语句;
条件控制语句;
}while(条件判断语句)
概念:执行循环体语句,如果条件判断成立,则继续执行
while、do...while循环区别:
- while循环不一定执行
- do ... while循环至少执行一次
for 循环
格式:
for(初始化语句;条件判断语句;条件控制语句){
循环体语句
}
break 和 continue
break
- break目前用于循环和switch语句中
- break 只能结束当前所属语句范围(最内层循环,所在的swith)
continue
- 强制结束本次循环,开始下一次循环
面向过程高级
方法的概念与格式
为什么需要方法?
如果逻辑代码变多,关系变复杂,一切都会很糟糕
概念
方法(函数):是一段具有独立功能的代码,可以被调取使用
优势
- 可以对独立功能的代码进行统一管理,避免代码的臃肿
- 统一代码不用重写,提高复用性
格式
c#
public static void 方法名(){
功能代码;
}
使用方法
方法名()
内存过程
从内存代码区,到栈内存,然后执行弹出的过程(先入后出)
⚠️ 变量在其定义的内存方法区内有效,运行完毕后内存会回收,变量的有效区称之为变量的作用域
方法的参数与返回值
形参
表示定义方法的时候,声明参数;如果不调用,则没有内存分配;
c#
//st就是形参
public static viod Shout(string st){
Console.WriteLine("老王林会~" + st);
}
实参
表示使用方法的时候,传入的参数
c#
string st = "wangwang~"
Shout(st);
//此时的st为实参
返回值
定义方法
c#
public static int summation(int a,int b){
return a+b
}
调用方法
c#
int sun = summation(10,20);
方法的设计与使用细则
方法的统一设计格式
public static 数据类型 方法名(类型 变量1,类型 变量2, .....){}
方法的设计步骤
- 明确方法功能,并起一个合适的名字
- 明确方法是否需要返回值,返回怎样的结果
- 明确方法是否需要参数,即用户传入什么
- 设计方法功能代码
方法使用细则
- 方法与方法之间为平级,禁止嵌套定义
- 方法的定义位置顺序与执行顺序无关,按照调用顺序执行
- void 返回类型的方法,也可用return语句结束当前方法,return后不加任何数据
返回值的其他用处
返回值可以作为函数运行成功与否的标志,比如bool类型,true表示运行成功,false表示运行失败
默认值参数
方法在定义时可以指定默认值,无需调用者提供
c#
public static viod Shout(string st = "wangwang"){
Console.WriteLine("老王林会~" + st);
}
当存在多个参数时,默认值必须从右到左给予
c#
public static viod Shout(string st,string nt = " = "wangwang"){
Console.WriteLine("老王林会~" + nt);
}
方法的重载
有时候我们会接到一些需求,例如:
- 设计三个方法,分别实现下面需求:
- 计算两个整数相加,求和返回
- 计算两个浮点数相加,求和返回
- 计算三个整数相加,求和返回
c#
public static int add1(int a, int b) {
return a + b;
}
public static double add2(double a, double b) {
return a + b;
}
public static int add3(int a, int b, int c) {
return a + b + c;
}
面对这样的需求,只是参数列表与返回值不同,但是需要多个不同的方法,显得特别乱,此时重载应运而生
方法重载(Overload)
-
在同一个类中,定义多个同名方法 ,每个方法有不同的参数类型 或参数数量 ,成为方法的重载
-
归纳总结
- 同一个类,方法名相同,参数不同
- 参数:个数、类型、顺序
- 注意:是否重载跟返回值无关
c#
//重写上面的需求,使用重载
public static int add(int a, int b) {
return a + b;
}
public static double add(double a, double b) {
return a + b;
}
public static int add(int a, int b, int c) {
return a + b + c;
}
方法重载与隐式类型转换
- 传入的参数,如果无法找到完全匹配的重载方法,则会尝试隐式类型转换
方法参数修饰符
需求
- 希望传给方法的参数在方法的内部更改,并影响到实参
举例
c#
int a = 3;
public static void doubleIt(int val){
return val *= 2;
}
int b = doubleIt(a);//6
此时希望a也改变
未完待续......