1.ref,out
函数参数的修饰符,当传入的值类型在内部进行修改时,或者引用类型参数在内部重新申明时,外部的值发生变化。
ref传入的值必须初始化,out不用(可读可写)
out传入的变量必须内部赋值,ref不用(只写)
实际都是传入一个指针,所以不能以此重载
2.params
变长参数,后面接数组
3.GC回收机制
C#的垃圾回收遍历堆上的可回收对象,如果该对象没有被任何变量,对象进行引用,那么就是回收对象。GC可以使程序员可以从复杂的内存问题中摆脱出来,从而提高了软件开发的速度、质量和安全性。
垃圾回收有多种算法,如 引用计数,标记清除,标记整理,复制集合。
大概原理:
0代内存-1代内存-2代内存。
分代算法是垃圾回收的一种算法,新分配的对象会被配置在第0代内存中
每次分配都可能会进行GC(0代内存满)
GC开始时,认为堆中全是垃圾,先进行标记对象,从根(全局对象、静态变量、局部对象、函数调用参数)检查引用对象,标记后为可达对象。否则不可达,视为垃圾。然后搬迁对象堆(挂起执行托管代码线程),释放未标记的对象,搬迁可达对象,修改引用地址.
大对象(83kb以上)总被认为是第二代内存,以减少性能损耗。
0代内存GC后幸存的对象进入1代,1代内存满时,对0代和1代进行GC,GC后幸存的对象进入2代,2代内存满时,对0,1,2代内存进行GC。
0代,1代保持比较小,一般加起来只有16m,2代大小有程序决定,可能达到几G。2代内存GC被称为full gc,通常成本很高,而0,1,代成本低。可以联系cpu的缓存。
个人理解为,数据的存活时间两极分化,要么活的很久,要么存活时间短。
显示调用GC:GC.Collect();
4.成员属性
get ,set,默认不加访问修饰符,要么低于属性的访问权限,不能都低于属性的权限,可以以此进行加密等操作 。
5.访问修饰符
public 公开
protected 保护 自己和子类可访问
private 私有
internal 当前程序集(Assembly,一个dll或者exe文件就是一个程序集)可以使用
protected internal:在当前程序集内使用和不在一个程序集内的子类中使用
private protected:只能在当前程序集内的子类中使用
6.索引器
访问修饰符 返回值 this[参数类型 参数名,.... ]
{
get{}
set{}
}
7.静态
静态成员存活于整个程序的生命周期。
常量const理解为特殊的静态static,但const必须初始化,且只能修饰变量。
静态构造函数,不能有访问修饰符和参数,只会自动调用一次,一般在静态构造函数中初始化静态变量。
静态函数 不用创建对象即可使用
8.扩展方法
一定写在静态类中,且为静态函数
9.运算符重载
关键字operator,一定为公共的静态方法,可以重载
public static 返回类型 operator运算符(参数列表);
10.is和as
is判断对象是否为指定类的对象或指定类的子类的对象,返回一个bool值
as将一个对象转换为另一个类对象,成功返回对象,否则返回null
感觉像C++的RTTI
11.拆箱装箱
object存值类型(装箱),值变引用,栈变堆
object转值类型(拆箱),引用变值,堆变栈
12.sealed
密封关键字,让类无法被继承,让虚方法或抽象方法无法重写,类似c++的final。
访问修饰符。
13.多态
编译时多态-函数重载,运行时多态的最常见的三种实现VOB
V,virtual(虚函数),O,overwrite,重写,B,base,父类(调用父类构造方法时用base关键字)
14.抽象,接口
抽象类,用abstract修饰,不能被实例化,可以包含抽象方法(纯虚函数),子类必须实现纯虚函数,用overwrite。
接口,interface,不包含成员变量,只包含方法,属性,索引器,成员不能为私有,不能实现,类可以继承多个接口,继承后需要实现所有成员。接口可以继承接口,不需要实现,不能实例化。一般表示行为。默认为public。
都遵循里氏替换原则。
15.结构体和类
数据集合使用结构体,继承多态使用类。值传递用的多时,用结构体,引用多时用类。
结构体为值类型,存储在内存栈,类为引用类型,存储在内存堆上。
结构体不能用protected,不能无参构造函数和析构函数,不能static,不能在自己体内申明自己一样的结构体。
结构体可以继承接口。
16.泛型约束
17.委托,事件,匿名函数,lambda
委托,可以理解为存储函数的变量,本质为一个类,定义函数的参数以及返回类型, 委托和函数的参数以及返回值需要一一对应,默认访问修饰符为public。通常存在在类成员以及函数参数。
public delegate 返回值 函数名(参数 参数名)
多播委托 委托可以存储多个函数 +=。
系统自定义了一些委托,如无参无返回值的Action,指定返回值的泛型委托等
事件,可以认为是特殊的委托,对委托进行安全的封装。
访问修饰符 event 委托类型 事件名
事件相较于委托,不能在类外部赋值与调用,但能+-移除记录的函数。只作为成员在函数或结构中。
匿名函数,没有名字的函数,一般在传参或者委托与事件赋值时使用。
lambda表达式语法,(参数列表)=> {函数体}; 参数类型可以省略,一般在自定义排序时使用的多。
18.逆变协变
协变,和谐的变化,父类变子类
逆变,不和谐的变化,子类变父类
用于修饰泛型,协变 out,逆变 in。在泛型接口或泛型委托中使用,为类型安全
out修饰的泛型参数类型只能作为返回值,in修饰的只能作为参数类型,自动识别委托的泛型之间是否有继承关系,子类体量比父类多,在作返回值和参数时有不同特性。
假如有两个类:A和AA,其中AA继承自A,如果此时有一个泛型接口IC<out T>,那么可以认为IC<A>能指向IC<AA>,即:IC<AA>和IC<A>的关系看着像AA和A的关系一样。
若参数同时为输入和输出参数,则必有一种类型不安全(不符合里氏替换原则),所以需要明确指定out,in。
19.反射和特性
反射在运行时实例化对象,操作对象。反射可以实现从对象外部了解内部的结构。
Type是反射的基础,访问元数据的主要方式。
Type t = typeof(Type);
MemberInfo[] infos = t.GetMembers(); 得到所有公共成员
ConstructorInfo[] ctors = t.GetConstructors();得到所有构造函数
ConstructorInfo info = t.GetConstructors(new type[0])得到无参构造
Test obj = info.Invoke(null) as Test;执行无参构造
ConstructorInfo info2 = t.GetConstructors(new type[]{type(int)});得到有参构造
Test obj = info.Invoke(new object[]{1,"1111"}) as Test;执行有参构造
FileInfo[] fieldInfos = t.GetFields();得到所有成员变量
MethodInfo[] methods = t.GetMethods()得到所有公共方法
类似的还有枚举GetEnumName,事件GetEvent,接口GetInterface等
Activator ,用于快速实例化对象,先得到Type,再
Test test =Activator.CreateInstance(testType /*,"有参构造"*/) as Test;
Assembly 程序集
Assembly assembly = Assembly.Load("程序集名称");(同一文件,不同文件下,用LoadFrom加载包含程序集清单的文件的名称或路径,用LoadFile加载文件的完全限定路径)
特性,为对象提供更多信息,比如[DllImport("Test.dll")]
自定义特性,继承特性类基类Attribute
20.补充
结构体本身是值类型,前提是不做为其他类的成员,结构体内的值存储在栈,结构体内的引用,具体的值存储在堆中。
数组本身为引用类型,值类型数组,堆中存储具体内容,引用类型数组,堆中存储地址