C# 基础
程序结构
- using System
- using 关键字用来程序中引入System命名空间,一个程序中可以有多个using
- namespace 关键字
- namespace 关键字用来声明一个命名空间,命名空间是类的集合
- class 关键字
- class 关键字用来定义一个类,类中通常用来存放程序中要使用的数据和函数(也叫方法)
- static void Main(string[] args)
- 在此代码中,Main 为定义的函数名称,Main函数是整个C#程序的入口
数据类型
- 基本数字类型: 字符串(string)、整形(int、uint、long、short、ushort、byte、sbyte)、字符类型(char)、浮点型(float、double、decimal)、布尔类型(bool);
- 变量名:
- 命名规则
- 数字、字母、下划线组成;
- 变量名不能以数字开头: num1
- 不能以关键字命名。namespace、class、 string等
- 命名规则
一、基本数据类型详解
值类型:整形、浮点型、字符、布尔类型(支持sizeof,默认不支持null)
引用类型:字符串 (不支持sizeof,默认支持null)
- 整形(整数)
- 有符号整形(包含负数): sbyte short int long
- 无符号整型(不包含负数):byte ushort uint ulong
- 计算机是以二进制的形式存储;存储的最小单位是:bit(字位)
- 1 btye = 8 bit
- 浮点型
- 字符类型
- 布尔类型
bool? isTrue = true; isTrue = false; // 可空类型:布尔类型自身不是可空类型;变成可空类型:bool? ==> 可空类型 isTrue = null;
- 字符串类型
// 字符串 // string str = null; // Console.WriteLine(str); // 字符串是由有序数列的字符数组组成的
[补充] 常量:
// 常量 const float num1 = 0.4f;
二、类型转换(隐式转换和显示转换)
[补充] 输入函数:获取用户在控制台上输入的内容;
- 基本类型(整形、浮点、布尔、字符)之间的转换
- int ==> long、short、float、char
- float ==> int、decimal、bool、char
- bool ==> char、int、float
- char ==> bool、float、int
- string转基本类型
- 所有类型要转换成String类型,隐式转换和显示转换都不行,只能用方法
- [type].parse()
- [variable].to…()
- 基本类型转string
- Convert.ToSring()
- [Variable].ToString()
三、运算符
- 赋值运算符:=
- 算术运算符:+ – * / %
- 特殊运算符: ++变量名 –变量名 变量名++ 变量名–
- ++ 在前,先运算后赋值
- — 在后,先赋值后运算
- 逻辑运算符
- &&(and)逻辑与:两边为真即为真,一边为假即为假
- || (or)逻辑或:两边味假即为假,一边为真即为真
- !(not) 逻辑非:真即假,假即真
- 三元运算符
- 变量名 = (条件) ? 值1:值2
- 杂项运算符
- sizeof
- typeof
- 进制转换
- 计算机 内存最小单位 bit
- 二进制:逢二进一 0 10 11 100
- 十进制:逢十进一 1 2 3 4
- 十六进制:逢十六进制 0 1 2 3 4 5 6 7 8 9 a b c d e f
- 十进制转其他进制可以用短除法
- 二进制转8进制(421)3转1
- 二进制转16进制(8421)4转1
- 其他进制转十进制用
- 十进制转二进制
- 方法一:短除法
- 找最近的除2
- 2^1 = 2;2^2 = 4; 2^3 = 8; 2^4 =16; 2^5 = 32;
- 2^3 = 64; 2^3 = 128; 2^3 = 256; 2^3 = 512; 2^3 = 1024;
- 二进制转十进制 2 4 16 128
- 【案例1】10010110 = 2(1) + 2(2) + 2(4) + 2(7) = 150
- 二进制转十六进制//
- 四转一:1111 = 1 + 2 + 4 + 8 = 15
- 【案例1】 1001 0110 1110 1111 ==》 0x96ef
- 十六进制转二进制:一转四
- 【案例1】0x1FA5 = 1 1111 1010 0101
- 负数的二进制
- 【案例1】求 -1 的二进制
- 先得到1的二进制:0000 0001
- 取反 1111 1110
- 加1: 1111 1111 (-1)
- 位运算符
- 是计算机最初的运算,一般都是对二进制进行操作
- 按位与运算 (&)
- 规则:参加运算的两个数,换算为二进制(0、1)后,进行按位与运算
- 两位同时为1, 结果才为1;否则,为0
- 【案例1】: 3 & 5
- 3 ==> 0000 0011
- 5 ==> 0000 0101 &
- 0000 0001
- 【案例2】: 10 & -10
- 10 ===》 0000 1010
- -10 ===》 1111 0101 ===> +1 1111 0110
- 0000 0010
- 按位或运算 ( | )
- 规则:参加运算的两个数,换算为二进制(0、1)后,进行按位或运算
- 有一个为1,结果才为1;否则,为0
- 按位异运算 ( ^ )
- 规则:参加运算的两个数,换算为二进制(0、1)后,进行按位异运算
- 只有当对应位上的数字不相同的时候,结果才位1;否者,为0
- 【案例2】: 10 & -10
- 10 ===》 0000 1010
- -10 ===》 1111 0101 ===> +1 1111 0110
- 1111 1100 ==》 -1 1111 1011 ==》取反 0000 0100 ==> -4
- 取反(~)
- 规则: 0 ==》 1; 1==》 0
- 【案例1】~10 (对十进制取反):
- ~ 0000 1010
- 1111 0101 => 1111 0100 => 0000 1011 -11
- 左移(<<)
- 二进制:进行左移运算,用来将一个二进制是的个位统一往左边移动若干位
- 【案例1】10 << 2
- 0000 1010 ==> 0010 1000==> 40
- 右移(>>)
- 【案例1】10 >> 2
- 0000 1010 ==> 0000 0010 ==> 2
流程控制语句
一、顺序语句
- 顺序结构是程序代码中最基本的结构,是指程序中的所有语句都是按书写顺序逐一执行的,代码从main()函数开始运行,从上到下,一行一行的执行,不漏掉代码
二、条件语句
- if
- if else
- if () if else() else()
- switch case; break;
三、循环语句
- while 循环
- do while 循环
- for 循环
- foreach 循环
- continue 跳出当前循环
- break 终止当前循环
四、跳转语句
- goto是跳转的意思,它的作用是当程序执行到goto语句会直接跳转到标识符所表示的程序位置,继续执行代码
数组
一、交叉数组 (交错数组)
int[][] array = new int[][] {new int[2] {1, 5}, new int[3]{1,2,3}}
二、多维数组
int[,] array = new int[,] { { 12, 23 }, { 12, 99 }, { 100, 2} }; int[,] array2 = { { 12, 23 }, { 12, 99 }, { 100, 2 } };
- 在C#中声明一个数组的语法
- data_type[] array_name;
- data_type 用来指定数组中元素的类型;[]用来指定数组的维度;array_name 为数组的名称;
- 给数组进行初始化
- 静态初始化
- 静态是在编译的时候,进行初始化
- 格式: data_type[] array_name = new data_type[] {}
- 简写: data_type[] array_name = {}
- 动态初始化
- 动态实在运行的时候,进行初始化
- 格式: data_type[] array_name = new data_type[length] {}
- 静态初始化
对象和类
一、字段
字段是类或结构体中的变量成员。例如:
class Octopus { string name; public int Age = 10 }
- 字段可用以下修饰符进行修饰:
- 静态修饰符:static
- 访问权限修饰符:public internal private protected
- 继承修饰符:new
- 不安全代码修饰符:unsafe
- 只读修饰符:readonly
- readonly修饰符防止字段在构造后进行变更。只读字段只能在声明时或在所属的类型构造器中复制。
- 线程访问修饰符:volatile
二、静态
- 语法区别:静态成员有关键字static,非静态成员无static修饰;
- 存储区别:静态成员变量存储位于程序的全局变量存储区,其作用域限制为类的内部,并且在整个程序运行期间只在内存中拥有一个存储位置,不会拷贝不会赋值,只是一个;
- 归属区别:静态成员隶属于类,是类的财产,无论对一个类创建多少个实例,它的静态成员都只有一个副本,在各个地方的改变都会改变其值;非静态成员隶属于它的成员,各自对象同一个非静态成员值的改变都不互相影响,有多少实例就有多少副本
- 生存周期区别:知道了存储位置的区别也就不难理解生存周期的差异了,静态成员只要分配了空间则在整个程序运行期间,它都是存在的,只有程序关闭之后,它的内存才会被GC回收期收回,不过作用域仍然只限制于类的内部,在类外部调用时需要使用类名加蒂安的方式访问;类的非静态成员的生存周期跟随于隶属于对象的生存周期,对象消亡则非静态成员就会被回收;
- 初始化顺序的区别:初始化都是最先初始化类的静态成员,然后才是非静态数据成员
三、结构体
struct <name> { 访问权限 type typename; 访问权限 type typename; }
四、枚举
- 枚举是一种值类型,它用于声明一组命名的常量,用enum关键字声明。说白了枚举是一个数据类型,就叫枚举类型,同样也是用来存储数据的。
- 枚举的作用
- 枚举能够是代码更清晰,更优雅,它允许使用描述性的名称表示整数值
- 枚举使代码更易于维护,有助于确保给定的变量指定合法、期望的值
- 枚举使代码更易输入
- 枚举一般什么时候用
(1)例1:
在案例中,我们需要重复使用到“星期一”到“星期天”这些特定的字符串,我们就可以来定义一个叫做“星期”的枚举。如果不定义成枚举,各位的写法就千奇百怪了,比如“周一”、“星期一”、“Monday”等,这三个表示的是同一天。
(2)例2:
比如说在”切水果“这个游戏中,里面有很多很多的水果,比如说香蕉、苹果、橘子、西瓜……等,这个时候我们呢是不是就可以定义一个叫”水果“的枚举类型,来存储这些水果。
(3)例3:
比如说在王者荣耀游戏中,通常有很多职业,比如说”战士“、”法师“、”射手“……等职业。我们就可以定义一个叫”职业“的枚举类型
其实定义枚举的目的就是为了规范一些数据的值。
enum <enum_name> { value1, value2, value3, … } enum RoleType { Mage, Archer, Assassin, Tank, Support, Warrior } public static void Main(string[] args) { RoleType roleType = RoleType.Mage; }
五、泛型
- 泛型方法:解决用一个方法,满足不同参数类型,做相同的事;
- 延迟声明:把参数类型的声明推迟到调用
- 不是语法糖,而是由框架升级提供的功能
- 需要编译器支持 + JIT支持
- 泛型:又叫马儿跑,又叫马儿不吃草![因为框架的升级]
六、方法
- 定义方法
<访问修饰符> <返回类型> <方法名称>(参数列表) { 方法主体 }
- 下面是方法的各个元素
- 访问修饰符:这个决定了变量或方法对于另一个类的可见性
- 返回类型:一个方法可以返回一个值,返回类型是方法返回的值的数据类型。如果方法不返回任何值,返回void
- 方法名称:是一个唯一的标识符,且是大小写敏感的。它不能与类中声明的其他标识符相同
- 参数列表:使用圆括号括起来,该参数是用来传递和接受方法的数据。参数列表是指方法的参数类型、顺序和数量。参数是可选的,也就是说一个方法可能不包含参数
- 方法主体:包含了完成任务所需的指令集
- ref和out的共同点:
- 可以让值类型达到像引用传递一样的效果
- 不同点:
- ref中传入实参的时候,如果传入的变量没有附上初始值,会报错;out中传入参数的时候,实参对应的变量赋不赋初始值都可以(一般不赋)
- ref修饰的形参在当前方法中,是可以不赋值的;out修饰的参数,在当前方法中,必须给out修饰的形参赋值
- 如何让一个方法有多个返回值
- 数组
- out
七、属性
// 简写 <访问修饰符> <返回类型> <属性名称> { get; set; } <访问修饰符> <返回类型> <属性名称> { get {return <字段>}; set {this.<字段> = value}; }
八、常量
- 静态常量:const 【编译】静态常量实在程序编译期间 确定并完成初始化的;
- 动态常量:readonly 【运行】在程序运行时获得初始化延迟到构造方法中,运行时常量;
九、修饰符s
- abstact
变量和参数
一、栈
栈是存储局部变量和参数的内存块。逻辑上,栈会在函数进入和推出时增加或减少
二、堆
堆是保存对象(例如引用类型的实例)的内存块。新创建的对象会分配在堆上并返回其引用。程序执行的过程中,堆就被新创建的对象不断填充。.net运行时的垃圾回收器会定期从堆上释放对象,因此应用程序不会内存不足。只要对象没有被“存活“的对象引用,它就可以被释放
C#高级特性
一、委托
二、事件
三、Lambda表达式
四、匿名方法
五、运算符重载