首页 > 代码库 > C#基础知识篇(五)-----------C#笔记
C#基础知识篇(五)-----------C#笔记
一.值类型和引用类型
1>值类型和引用类型将我们学过的数据类型划分成了两部分. 划分的依据是不同类型的数据在内存中(堆栈)存储的结构不同.
2>值类型:所有的数值类型:long int short byte ulong uint ushort sbyte decimal duoble float char bool 枚举 结构
3>引用类型:string,arry(数组),类(class)
4>不管是值类型还是引用类型赋值都是将数据copy一份将副本赋给变量,不同的是值类型拷贝的是真实值,引用类型拷贝的是变量的内存地址,
即:值类型赋的是真实值的副本,那么一个变量的值改变而不影响另一个变量的值;而引用类型因传递的是内存地址(即:都同时指向一个变量),若一个变量的值发现改变另一个的值也发生改变。
5>Null值,只能是引用类型的值。如果一个引用类型变量的值为:Null就代表他没有指向任何对象。
二.常量
1> 什么叫做常量?被const修饰的数据叫做常量。
2> 语法:const 数据类型 常量名称=值;
3> 常量一旦声明,他的值就无法改变。(即:一旦声明就必须赋值,因为常量就是在声明后不能修改,则只能在定义是赋值)
4> 我们声明1个常量,在编译器编译的时候,会将声明常量的那句话去掉,然后在使用到常量的值的地方用常量的值直接代替。所以就算可以改变,也没有效果.也没有任何意义.
5> 常量声明的同时就必须要为其赋值,常量的赋值不能有变量参与,因为变量的值在运行的时候才确定,若可以那就违背了常量的定义。即:常量编译时已确定,变量运行时才确定。
三.Readonly(只读)
1> readonly只能用来修饰字段,不能修饰局部变量。(因为readonly只能在构造函数中赋值,即:创建对象的时候。而局部变量是在方法(实例方法)被调用的时候声明和创建等方法结束后销毁,
即时间段:在创建对象之后。)
2> 只读子段只能取值不能改值。
3> 如果我们在为类声明字段的同时为字段赋了初始值,但是在C#编译器编译的时候,它会将赋值的代码放在构造函数中。因为为字段赋值的代码,是执行代码 只有CPU执行才会有效果.
4> 只读字段的值 只能在构造函数中改变,其他的地方不能改变
5> Readony和const的区别?const是编译时要确定值,而readonly可以在运行时确定。(编译在前运行在后,因为代码会先经编译器编先检查语法,再进行编译成一个程序集然后再运行)
6> 在编译时可以确定值则用const,在运行时才能确定用readonly.
四.枚举
1> 语法:
访问修辞符 enum 枚举名 :整形的类型(指定枚举值对应整型数的类型)
{
枚举成员
}2> 在枚举中定义枚举成员其中用逗号分隔
3> 枚举的值的类型只能为枚举型,不能带双引号(带双引号就是字符串),也不能为int型否则起冲突。
4> 枚举里面只能定义枚举项,而每一个枚举项都有与之对应的一个int数,这个数从0开始一次递增(默认)。
a. 我们可以使用强制转换的语法 将1个枚举类型的变量的值 强制转换为其所对应的int类型的数值
例:
Direction dir = Direction.North;(Direction为枚举类型)
int i = (int)dir;
b. 我们可以使用强制转换的语法,将1个int类型的数据转换为其所对应的枚举值.
例:int i = 3;
Direction dir = (Direction)i;
c. 我们可以手动的为每1个枚举值指定对应的int类型的数据. 在声明枚举值的时候 通过赋值符号 为其指定1个int类型的数.
5> 将字符串转换成枚举型
1>区分大小写
(转换的枚举类型)Eum.Parse(typeof(转换的枚举类型),待转换的字符串)
2>不区分大小写
(转换的枚举类型)Eum.Parse(typeof(转换的枚举类型),待转换的字符串,true)
6> 枚举是个值类型,我们一般把枚举定义在跟类一个级别,因为这样整个命名空间都可以访问它。当然也可以定义在类中。
五.结构
1> 结构和类特别相似,在结构中可以定义字段,方法,属性,构造函数。(因为结构是在C中传承下来的,而C是面向过程的)
2> 结构体也需要创建对象来对结构中的成员进行调用,与类的区别是结构体可以通过new关键字来创建,也可以不通过new关键字来创建,声明一个结构类型的变量就可以了,
这个变量就是一个对象(结构只是与类非常相似并不是一样,还是有语法区别的)。通过对象名点成员来调用。
3> 声明语法:
[访问修饰符] struct 结构名称
{
结构成员;
}4> 结构和类的区别:
a. 类是class声明 结构体是struct声明
b. 结构体中虽然可以声明字段,但是声明字段的同时不能给字段赋值.否则报错。
c. 结构体中虽然可以定义构造函数,但是你不能写1个无参数的构造函数. 因为无论如何 编译器多会为结构体生成1个无参数的构造函数.
d. 在结构体的构造函数中,必须要为这个结构体对象的每一个字段赋值.
e. 在创建结构体对象的时候. 可以使用new关键字来创建. 但是我也可以不使用new关键字. 使用new关键字来创建对象: 结构体中所有的字段就已经有值了.可以直接使用. 不使用new关键创建对象:
结构体中的字段没有值,所以在使用字段的值之前 必须要为字段赋值. 原因在于: 使用new关键字创建对象 调用了构造函数,而结构体的构造函数要求必须为所有的字段赋值, 哪怕是它自己生成的无
参数的构造函数(为所有的字段赋默认值). 所以使用new关键字创建结构体对象 这个结构体对象的所有的字段都已经有值了. 如果直接声明1个结构体变量而不使用new关键字,没有调用构造函数,
所以字段也就没有值.
f. 在构造函数中为属性赋值,编译器不认为是在对字段赋值,因为属性不一定是在操作字段。
g. 结构体是1个值类型.类是1个引用类型.
5> 结构体是一个值类型. 在创建结构体对象的时候,结构体对象直接存储在变量中. 结构体变量之间相互赋值的时候,是逐个拷贝字段的值.
六.垃圾回收(GC)
1> 我们声明变量,创建对象都会在内存中开辟空间,因为内存有限所以这些空间必须回收,不回收会死机,会内存溢出,这就是垃圾回收的意义。
2> C#托管代码不需要担心内存的回收,因为系统以及.Net框架会帮助我们完成这些.
3> 栈空间的局部变量会在程序执行他们所在的大括符结束时会被系统立即被回收。
4> 堆空间的对象在没有任何变量指向他时,就会被标记成垃圾对象。等待垃圾回收器(GC)的回收,GC属于CLR的。GC回收垃圾的频率是由CLR控制的,程序员无法干预。
5> GC.Collect();立即要求GC来回收堆空间中的垃圾对象。
6> 栈空间的局部变量若要想提前回收,则需要在回收的局部变量外加“{}“,如:
{
int a=100;
Console.WriteLine(a);
在这里只用a一次后面都不用了,就把a立即回收掉。
}
七.析构函数(终结者函数)
1.> 语法:
~ 类名()
{
方法体;
}2.> 析构函数不能带参数 不能带访问修饰符;析构函数在对象被GC回收的时候.自动执行;
3.> 在对象创建的时候 会执行构造函数 在对象被回收的时候 会执行析构函数. 析构函数的作用:一般情况下我们做一些善后工作.