C#核心学习笔记
写在最前
- 这篇笔记对应的是唐老狮的C#四部曲──C#核心课程地址
一、面向对象的概念
- 面向对象是一种对现实世界理解和抽象的编程方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行程序开发,更贴近事物的自然运行模式。
- 人话:万物皆对象,用程序来抽象对象。
- 套路:用中文去形容一类对象,把对象的共同点提取出来,然后用程序语言把它翻译过来,带着对象的概念在程序中去使用它们。
二、面向对象-封装
类和对象
- 基本概念
- 具有相同特性、相同行为的一类事物的抽象
- 类是对象的模板,可以通过类创建出对象
- 类声明语法
1 | //一般声明在namespace中 |
3、类对象声明
1 | //类是自定义变量类型,类对象是一个变量。 |
成员变量和访问修饰符
- 成员变量基本规则
- 声明在类语句块中,用来描述对象的特征
- 可以是任意类型
- 数量不做限制
- 是否赋值根据需求来定
- 可以在类中声明和自己相同类型的成员变量,但是不能实例化(可以使用null)
- 访问修饰符
- public 公共的,外部可以用
- private 私有的,自己内部可以用
- protected 保护的,自己内部和子类可以用
- 成员变量的初始值
- 值类型
- 数字类型:0
- bool类型:false
- 引用类型
都为null - 小技巧:default(类型)会返回默认值
- 值类型
成员方法
- 声明
1 | //1. 声明在类语句块中 |
构造函数和析构函数
- 构造函数
- 实例化对象时会调用的用于初始化的函数
- 如果不写,默认存在一个无参构造函数
1 | //没有返回值 |
- 析构函数
- 当引用类型的堆内存回收时,会调用该函数
- 对于需要手动管理内存的语言(c++),需要在析构函数中做内存回收的处理
- c#中存在垃圾回收机制(GC),基本不会使用这个函数
- 析构函数是垃圾真正被回收的时候调用,而不是产生垃圾就调用
1 | ~类名() |
- 垃圾回收
- 垃圾回收的过程是遍历堆(heap)上动态分配的所有对象,通过识别它们是否被引用来确定哪些对象是垃圾,哪些对象仍然在是被使用。
- 所谓的垃圾就是没有被任何变量,对象引用的内容
- GC只负责堆内存的垃圾回收,引用类型的分配和释放都是垃圾回收机制管理的。
- 具体原理:
- C# 的垃圾回收器主要采用分代式垃圾回收算法,它将堆分为三代:①第 0 代:新创建的对象通常会被分配到第 0 代。当第 0 代满时,垃圾回收器会执行一次回收操作。②第 1 代:一些在第 0 代中经过一次垃圾回收后仍然存活的对象会被提升到第 1 代。③第 2 代:存活时间更长的对象会从第 1 代提升到第 2 代。大对象(通常大于 85,000 字节)通常直接分配到第 2 代。
- 垃圾回收过程中,从根对象开始,遍历对象图,标记所有可达对象。清除阶段会回收所有未标记的对象,释放它们占用的内存。然后将所有可达对象进行搬迁,集中,并修改引用地址。
- 手动触发垃圾回收,较少使用,一般在loading时使用,消耗较大。GC.Collect();
成员属性
- 基本概念
- 用于保护成员变量
- 为成员属性的获取和赋值添加逻辑处理
- 解决3P的局限性──将读和写解绑
- 基本语法
1 | //访问修饰符 属性类型 属性名 |
索引器
- 基本概念
- 让对象可以像数组一样通过索引访问其中元素,使程序直观。结构体里面也支持索引器
- 语法
1 | //访问修饰符 返回值 this[参数类型 参数名,参数类型 参数名,……] |
静态成员
- 静态关键字static修饰的成员,直接使用类名点出使用
- 原理
- 当程序运行时,对于包含静态成员的类型,CLR(公共语言运行时)会在加载该类型时为其静态成员分配专门的内存区域。这个内存区域是全局唯一的,无论创建多少个该类型的实例,静态成员都只有一份内存空间。
- 在类的内部,静态成员可以直接访问其他静态成员,无需通过类名。但在访问非静态成员时,会引发编译错误,因为非静态成员依赖于具体的对象实例,而静态成员在没有实例的情况下也可能被调用。
- 静态成员的生命周期从类型被加载到 CLR 中开始,直到程序域(AppDomain)卸载时结束。在整个程序运行期间,静态成员始终存在于内存中,它的状态会一直保持,除非被显式修改或程序结束。
- 静态成员可以在声明时进行初始化,也可以在静态构造函数中进行初始化。静态构造函数是一种特殊的构造函数,它只在类型第一次被使用之前自动调用一次,用于对静态成员进行初始化操作。
- 常量和静态成员的区别
- 相同:都可以通过类名点出使用
- 不同:const必须初始化,不能修改,static无这个限制
- 不同:const只能修饰变量,static可以修饰其它
- 不同:const不惜写在访问修饰符后面,static无这个限制
静态类和静态构造函数
- 静态类
- 用static修饰的类,只能包含静态成员,不能被实例化
- 一般是工具类,唯一性
- 静态构造函数
- 用static修饰的构造函数
- 静态类和普通类都可以使用
- 不能有访问修饰符和参数
- 只会调用一次
- 作用是在静态构造函数中初始化静态变量
拓展方法
- 基本概念
- 为现有的非静态的变量类型添加方法
- 提升程序拓展性,不需要再在对象中重新写方法,不需要继承来添加方法
- 为别人封装的类型写额外的方法
- 一定写在静态类中,一定是个静态函数,第一个参数为拓展目标且用this修饰
- 基本语法
1 | //访问修饰符 static 返回值 函数名(this 拓展类名 参数名,参数类型 参数名……) |
运算符重载
- 基本概念
- 让自定义类和结构体使用运算符,使用关键字operator
- 一定是一个公共的静态方法,返回值写在operator前,逻辑处理自定义
- 条件运算符需要成对实现,一个符号可以多个重载,不能使用ref和out
- 基本用法
1 | //public static 返回类型 operator 运算符(参数列表) |
- 可重载和不可重载的运算符
- 可重载
①算数运算符
②逻辑运算符中的逻辑非( ! )
③位运算符
④条件运算符 - 不可重载
①逻辑运算符中的逻辑与( && )和逻辑或( || )
②索引符 [ ]
③强转运算符 ( )
④特殊运算符 点 . 三目运算符? : 赋值符号 =
- 可重载
内部类和分部类
- 内部类
- 在一个类中再声明一个类
- 使用时需要用包裹者点出自己
- 亲密关系的变现
- 访问修饰符作用很大
- 分部类
- 把一个类分成几个部分声明,关键字:partial
- 分部描述一个类,增加程序的拓展性
- 分部类可以写在多个脚本文件中,分部类的访问修饰符要一致且写在关键字前面,分部类中不能有重复成员
- 分部方法
- 将方法的声明和实现分离,在方法前面加分部关键字partial
- 不能加访问修饰符,默认私有
- 只能在分部类中声明,返回值只能是void
- 可以有参数,但不能用out关键字
三、面向对象-继承
继承的基本规则
- 概念
- 一个类A继承一个类B,类A会有类B的所有成员、所有特征和行为
- 被继承的类:父类、基类、超类;继承的类:子类、派生类;
- 子类可以有自己的特征和行为
- 单根性:子类只能有一个父类
- 传递性:子类可以间接继承父类的父类
- 语法
1 | class MyClass:FatherClass |
- 父类和子类同名成员
- 极不建议父类和子类都存在同名成员,在子类的实例中,该字段会隐藏父类字段,从而访问到子类的对应字段。
- 可以用new关键字在子类同名字段声明时显示隐藏父类同名字段。
里氏替换原则
- 概念
- 任何父类出现的地方都可以用子类代替
- 父类容器装子类对象,因为子类对象包含了父类的所有内容(不能用子类容器装父类对象)
- 方便进行对象存储和管理
- 语法
1 | class GameObject |
- is 和 as
- is
①判断一个对象是否是指定类对象
②返回值:bool,是为真,不是为假 - as
①将一个对象转换为指定类对象
②返回值:指定类型对象,成功返回指定类型对象,失败返回null
- is
继承中的构造函数
- 概念
万物之父和装箱拆箱
密封类
四、面向对象-多态
五、面向对象关联知识点
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 橙菌!