C#基础整理

静态方法

  1. 特点
    1. 生命周期一旦创建应用结束才会结束
    2. 全局
    3. 效率高(常驻内存)
  2. 用处
    1. 用户登录信息
    2. 系统配置信息
    3. 系统设置
    4. SQLHelper
  3. 缺点
    1. 静态东西创建多了占用内存会很大,对于使用频率比较高的内容适合,这样可以减少频繁的内存申请
  4. 调用
    1. 静态方法调用非静态方法不能直接调用,需要new一下非静态方法所在的类在调用

构造方法

  1. 用处:初始化对象或数据
  2. 特点:默认是一个无参构造方法,可以重载

析构方法

  1. 作用:释放对象,GC垃圾回收器会调用
1
2
3
4
5
Close方法关闭对象,没有完全释放
Dispose方法完全释放,需要实现IDisposable接口

垃圾回收机制
回收非托管资源:Windows窗口句柄、数据库连接、GDI对象、独占文件锁等等

虚方法virtual

  1. 作用:允许子类/派生类进行重写override,实现不一样的功能
  2. 特点:好维护

抽象方法abstract

  1. 定义:一定要写在抽象类里面,而且不能new不带方法体
  2. 与接口的区别:
    1. 派生类只能继承单个抽象类,派生类可以继承多个接口
    2. 抽象类里可以定义普通方法、虚方法等,接口只能写规范不能写具体的实现
    3. 抽象类一般用于不会经常改动的对象(人->男人),接口适用于经常修改,只是一个规范,锲约,定义,功能
      1
      2
      3
      4
      虚方法和抽象方法的区别:
      1. 虚方法必须有实现部分,抽象方法没有提供实现部分。抽象方法只定义具体实现需要在派生类中完成。
      2. 抽象方法只能在抽象类中声明,虚方法不是。如果类包含抽象方法,那么该类也是抽象的,也必须声明类是抽象的。
      3. 抽象方法必须在派生类中重写,这一点和接口类似,虚方法不需要再派生类中重写,对于虚方法派生对象可以重写虚方法里的方法也可以不重写,但是抽象方法的派生对象必须重写抽象类中的抽象方法。

扩展方法ExtendMethod

  1. 定义:在非泛型静态类中定义的静态方法
  2. 使用场合:
    1. 调用密封类中的对象,属性或者方法(扩展密封类)
    2. 扩展接口
    3. 在linq链式编程
  3. 示例
    1
    2
    3
    4
    5
    6
    7
    public static class InvokeCenter{
    public static void InvokeManager<T>(this T showClass) where T:new(){

    }
    }

    把密封类作为参数传递进去

泛型

什么是泛型

  1. 定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。解决功能模块相似但处理的数据类型不一样,object带来的装箱拆箱性能损耗,类型参数是在其实例化泛型类型的一个变量时,客户端指定的特定类型的占位符(T)

  2. 优点:通用性

  3. 泛型约束:关键字where

    1. new()约束 例子:where T:new() 表示T类型只接受带一个无参数的构造函数。多个约束的情况下new约束必须放到最后
    2. 结构类型struct/值类型/引用类型约束
    3. 自定义类型约束
      1
      2
      值类型:struct、int、枚举、doubel等
      引用类型:数组、接口、委托、类、object、字符串
  4. 协变和逆变:针对泛型接口和泛型委托来说的。out代表协变,in代表逆变。协变只能返回结果不能做参数,逆变T只能做参数,不能做返回值

    1. 使用场景:父类通过子类实例化(逆变in)或者子类通过父类实例化(协变out)的场景
  5. 泛型的用处

    1. 让泛型类、泛型方法、泛型接口、泛型委托更通用
    2. 约束
    3. 协变逆变

反射

  1. exe/dll主要区别是exe文件有入口—metadata(元数据:描述exe/dll文件的数据清单)—-反射可以读取metadata
  2. 反射:操作matedata的一个类库,可以把它当成一个可以用来读取或者操作元数据的小工具
  3. 使用场景:MVC/ORM/AOP等
  4. 反射可以动态读取并且能读取私有对象,通过反射加载dll文件
  5. 实例
    1. 加载dll: Assembly.LoadFile(“xxxx.dll”); 或者 Assembly.LoadFrom(“xxxx.dll”);
    2. 使用反射创建对象
      1. 加载dll:Assembly asb = Assembly.LoadFile(“xxxx.dll”);
      2. 获取类型(完整类型名称): Type type = asb.GetType(“类名”);
      3. 创建类型:
        1. 不带参数:object obj = Activator.CreateInstance(type)
        2. 带参数:object obj = Activator.CreateInstance(type, new object[]{对应的参数类型,多个参数用逗号隔开});
      4. 类型转换:把obj转换为具体的实例类型(as)
    3. 使用反射创建具有私有构造函数的对象
      1. Assembly asb = Assembly.LoadFile(“xxxx.dll”);
      2. Type type = asb.GetType(“类名”);
      3. object obj = Activator.CreateInstance(type, true);
    4. 使用反射创建泛型类
      1. Assembly asb = Assembly.LoadFile(“xxxx.dll”);
      2. Type type = asb.GetType(“泛型名称并且加上泛型所需参数个数,例如需要三个参数表示为:xxxClass`3”);
      3. Type makeType = type.MakeGenericType(new Type[] {typeof(int),typeof(string),typeof(bool)})
      4. object obj = Activator.CreateInstance(makeType)
    5. 使用反射调用方法
      1. Assembly asb = Assembly.LoadFile(“xxxx.dll”);
      2. Type type = asb.GetType(“类名”);
      3. MethodInfo methodInfo = type.GetMethod(“方法名”);
      4. methodInfo.Invoke(methodInfo,new object[]{参数});
    6. dll文件名+类型名称+方法名称类比mvc路由http://localhost:4500/Home/index
    7. 总结
      1. 获取dll文件
      2. 获取到类型名称
      3. 实例化类型 Activator.CreateInstance
      4. 找到方法 GetMethod
      5. 确定方法参数类型 MakeGenericType
      6. 调用 invoke
泛型实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public T Find<T>(int id){
Type type = typeof(T);
string sql = $"SELECT {string.join(",",type.GetProperties().Select(p=>p.Name))} from { type.Name} where id = {id}";

using(SqlConnection conn = new SqlConnection(connStr)){
SqlCommand cmd = new SqlCommand(sql,conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
object obj = Activator.CreateInstance(type);
if(reader.Read()){
foreach(var prop in type.GetProperties()){
prop.SetValue(obj,reader[prop.Name]);
}
}
read.Close();
return (T)obj;
}
}
特性
  1. 在方法或者类上标注的方法
  2. 使用场景:数据验证
  3. 特性的步骤:
    1. 定义特性
    2. 标记
    3. 调用
委托
  1. 委托是引用类型,保存函数的指针,指向一个函数。调用委托的时候就是在执行被指向的函数。关键字:delegate
多播委托
  1. 每一个委托都是继承自MulticastDelegate
  2. 带返回值的多播委托只会返回最后一个方法的值
  3. 多播委托可以用加减号来操作方法的增加或减少
  4. 给委托传递相同方法时,生成的委托实例也是相同的(即是同一个委托),如果给委托传递的是匿名方法则对应不同的委托实例
总结
  1. 泛型:把类型做到通用
  2. 反射:读取dll文件描述信息(matedata)的一个类库
  3. 特性:是一个类,继承自Attribute。贴标签,贴上标签就有新的功能,本质就是AOP的另一种实现方式
  4. 委托:指向方法的指针
事件
  1. 事件就是委托的安全版本
  2. 在事件内的外部不能用=号来操作,只能用+=
  3. 在定义事件类的外部不能调用事件
  4. 定义事件的关键字是event,只需要在委托前面加上event即是事件
  5. 示例
    1
    2
    3
    4
    5
    delegate void StudentDelegate()

    class InvokeDefine{
    public event StudentDelegate StudentEvent;
    }