Initial Obsidian notes backup
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
# 内部类
|
||||
概念:
|
||||
也叫==嵌套类==
|
||||
就是把一个类写在另一个类的内部
|
||||
本质上它还是类,所以仍然是[[值类型和引用类型|引用类型]]
|
||||
|
||||
通常用法:
|
||||
1. 给外部类当“小零件”用,不想单独暴露出去
|
||||
2. 把关系很紧密的类型写在一起,减少命名污染
|
||||
3. 配合[[成员变量和访问修饰符|访问修饰符]]控制谁能访问
|
||||
|
||||
语法:
|
||||
```Csharp
|
||||
class Outer
|
||||
{
|
||||
public class Inner
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
class Person
|
||||
{
|
||||
private string name = "小明";
|
||||
|
||||
public class Pet
|
||||
{
|
||||
public void LookOwner(Person p)
|
||||
{
|
||||
cw(p.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Person p = new Person();
|
||||
Person.Pet pet = new Person.Pet();
|
||||
pet.LookOwner(p); //输出 小明
|
||||
```
|
||||
↑ `Pet` 是 `Person` 的内部类,所以外部使用时一般写成 `Person.Pet`
|
||||
|
||||
注意:
|
||||
1. 更规范的说法一般是==嵌套类(nested class)==
|
||||
2. ==类中的内部类如果不写访问修饰符,默认是private==
|
||||
3. 外部访问时通常写 `外部类名.内部类名`
|
||||
4. ==C# 的内部类不会自动绑定外部类对象==,想访问外部对象的数据,一般要把外部类对象传进去
|
||||
5. 内部类主要是为了==封装和组织代码==,不是继承
|
||||
|
||||
----
|
||||
# 分部类
|
||||
概念:
|
||||
在C#里更常见的叫法是==分部类==
|
||||
用 `partial` 关键字把==同一个类拆到多个文件或多个位置==
|
||||
编译时会把这些内容==合并成同一个类==
|
||||
|
||||
通常用法:
|
||||
1. 一个类太长了,拆开写更清楚
|
||||
2. 自动生成代码和手写逻辑分开
|
||||
3. 多人协作时减少都挤在一个文件里的冲突
|
||||
|
||||
语法:
|
||||
```Csharp
|
||||
public partial class Player
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
在另一个文件里也可以继续写:
|
||||
```Csharp
|
||||
public partial class Player
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
//Player_Base.cs
|
||||
public partial class Player
|
||||
{
|
||||
public string name;
|
||||
|
||||
public void Move()
|
||||
{
|
||||
cw("移动");
|
||||
}
|
||||
}
|
||||
|
||||
//Player_Fight.cs
|
||||
public partial class Player
|
||||
{
|
||||
public int atk;
|
||||
|
||||
public void Attack()
|
||||
{
|
||||
cw("攻击");
|
||||
}
|
||||
}
|
||||
|
||||
Player p = new Player();
|
||||
p.Move();
|
||||
p.Attack();
|
||||
cw(p.atk);
|
||||
```
|
||||
↑虽然写在两个文件里,但编译后它们还是==同一个 `Player` 类==
|
||||
|
||||
注意:
|
||||
1. ==每一部分都要写 `partial`==,少一处都不行
|
||||
2. 一般要保证它们是==同名、同命名空间==的一组类型
|
||||
3. 分部类是==编译时合并==,不是继承,也不是复制出多个类
|
||||
4. 很适合配合工具自动生成代码,比如“工具生成一部分,自己手写一部分”
|
||||
5. `partial` 不只类能用,结构体和接口也能用,但这节先记类
|
||||
6. 不要为了拆而拆,拆太碎反而更难找代码
|
||||
|
||||
----
|
||||
# 分部方法
|
||||
概念:
|
||||
分部方法就是写在==分部类==中的特殊方法
|
||||
也是用 `partial` 关键字声明
|
||||
一般是一边先声明“这里留个钩子”,另一边再决定要不要实现
|
||||
|
||||
通常用法:
|
||||
1. 给自动生成代码留扩展点
|
||||
2. 把“框架流程”和“自定义逻辑”拆开
|
||||
3. 某些逻辑可选,有需要时再补实现
|
||||
|
||||
语法:
|
||||
先声明:
|
||||
```Csharp
|
||||
partial void OnCreated();
|
||||
```
|
||||
再在同一个分部类型的另一部分里实现:
|
||||
```Csharp
|
||||
partial void OnCreated()
|
||||
{
|
||||
cw("创建完成");
|
||||
}
|
||||
```
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
//Player_Base.cs
|
||||
public partial class Player
|
||||
{
|
||||
public Player()
|
||||
{
|
||||
OnCreated();
|
||||
}
|
||||
|
||||
partial void OnCreated();
|
||||
}
|
||||
|
||||
//Player_Extend.cs
|
||||
public partial class Player
|
||||
{
|
||||
partial void OnCreated()
|
||||
{
|
||||
cw("玩家初始化完成");
|
||||
}
|
||||
}
|
||||
```
|
||||
↑ 这种写法很适合“主逻辑在自动生成文件里,扩展逻辑在自己文件里”
|
||||
|
||||
注意:
|
||||
1. ==分部方法只能写在分部类型里==,普通类里不能单独这么用
|
||||
2. 它本质上是“声明部分”和“实现部分”配对
|
||||
3. 如果只是最经典那种可选分部方法,一般写法是==没有访问修饰符、返回 `void`、不能有 `out` 参数==
|
||||
4. 这种“可选分部方法”如果没写实现,==编译器会把声明和调用一起移除==
|
||||
5. ==如果你给它加了访问修饰符,或者返回值不是 `void`,通常就不能再省略实现==
|
||||
6. 所以记忆上可以理解成:简单钩子可以不实现,复杂正式方法通常必须实现
|
||||
|
||||
----
|
||||
引用:
|
||||
1. Microsoft Learn: [Nested types (C# Programming Guide)](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/nested-types)
|
||||
2. Microsoft Learn: [Partial Classes and Members (C# Programming Guide)](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods)
|
||||
3. Microsoft Learn: [partial type (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-type)
|
||||
4. Microsoft Learn: [Partial member (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-member)
|
||||
|
||||
#封装
|
||||
#核心
|
||||
@@ -49,3 +49,7 @@
|
||||
|
||||
注意:
|
||||
|
||||
|
||||
#封装
|
||||
#核心
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ p.Name = xxx;
|
||||
↑最简单的防止money为负数的逻辑
|
||||
|
||||
注意:
|
||||
==get必须有返回值==
|
||||
成员属性不加访问修饰符,会使用成员变量声明时的访问权限
|
||||
==get和set也可以加访问修饰符,但是不能大于成员属性前访问修饰符的权限==
|
||||
可以只有一个set或只有一个get(只能得或只能改),但是通常没人这么干
|
||||
@@ -82,4 +83,8 @@ public float Height
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
#封装
|
||||
#核心
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
# 构造函数:
|
||||
概念:
|
||||
实例化时,用于初始化的函数
|
||||
不写默认有一个无参构造函数
|
||||
==可以重载==
|
||||
|
||||
通常用法:
|
||||
自定义初始化规则
|
||||
|
||||
语法:
|
||||
访问修饰符 类名(){}
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
class Person()
|
||||
{
|
||||
public string name;
|
||||
public int age;
|
||||
public Person()
|
||||
{
|
||||
name = "默认值";
|
||||
age = 默认值;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
this关键字:
|
||||
this指当前类声明的成员变量
|
||||
```Csharp
|
||||
class Person()
|
||||
{
|
||||
public string name;
|
||||
public int age;
|
||||
public Person()
|
||||
{
|
||||
name = "默认值";
|
||||
age = 默认值;
|
||||
}
|
||||
public Person(int age,string name) //重构
|
||||
{
|
||||
this.name = name;
|
||||
//后面的name是传递的参数,this.name是最上方public int出来的
|
||||
this.age = name;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
特殊写法:
|
||||
通过this重用构造函数代码,即先调用无参构造函数,然后在调用这个特殊写法的构造函数
|
||||
语法:访问修饰符 构造函数名(参数列表):this(【可选】参数1,参数2.....)
|
||||
例子:
|
||||
```Csharp
|
||||
public Person(int age, string name):this(age)
|
||||
{
|
||||
balabala
|
||||
}
|
||||
```
|
||||
过程:先调用无参Person构造函数,然后寻找只有构造单个参数age的构造函数进行初始化
|
||||
|
||||
注意:
|
||||
==函数名和类名必须相同==
|
||||
==没有特殊用途,一般都是public==
|
||||
|
||||
==如果写了有参构造函数且自己没有保留无参构造函数,那么类在实例化时只能使用有参构造函数且无法使用无参构造函数==
|
||||
|
||||
|
||||
|
||||
----
|
||||
# 析构函数
|
||||
概念:
|
||||
当引用类型堆内存被回收时,会调用该函数
|
||||
对于需要手动管理内存的语言(C++),需要在析构函数中做一些内存回收处理
|
||||
C#有自动垃圾回收机制GC
|
||||
Unity中基本不用管
|
||||
|
||||
通常用法:
|
||||
|
||||
|
||||
语法:
|
||||
```Csharp
|
||||
~类名()
|
||||
{
|
||||
}
|
||||
```
|
||||
案例:
|
||||
```Csharp
|
||||
~Person()
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
|
||||
----
|
||||
# 垃圾回收
|
||||
垃圾回收(GC)
|
||||
通过遍历堆Heap上动态分配的所有对象
|
||||
通过识别他们是否被引用来确定哪些对象时垃圾,哪些对象仍然需要引用
|
||||
垃圾:没有变量或对象引用的内容
|
||||
如果是垃圾就要被回收释放
|
||||
|
||||
一般都是==被动触发(会造成卡顿)==,所以游戏一般需要手动执行垃圾回收
|
||||
语法:GC.Collect();
|
||||
==GC会造成卡顿,所以在加载Loading时一般会调用==
|
||||
|
||||
垃圾回收有多种算法
|
||||
引用计数
|
||||
标记清楚
|
||||
标记整理
|
||||
复制集合
|
||||
|
||||
注意:
|
||||
GC只负责Heap内存的垃圾祸首
|
||||
引用类型都是在Heap中的,所以他需要GC来进行管理
|
||||
|
||||
栈Stack上的内存时系统自动管理的
|
||||
所以不需要GC
|
||||
|
||||
C#中垃圾回收机制的大概原理
|
||||
他会把内存分为0,1,2代内存
|
||||
代的概念是垃圾回收中的一种算法需要
|
||||
新分配的对象都会被配置在第0代内存中
|
||||
每次分配都可能会进行垃圾回收(一般来说0代内存满了就会触发)
|
||||
在第一次内存回收过程开始时,垃圾回收器会认为堆中全是垃圾,会进行一下两部
|
||||
1.标记对象,从根(静态参数、方法参数)开始检查引用对象,标记后为可达对象,未标记就是不可大对象
|
||||
不可达对象就会认为是垃圾
|
||||
2.搬迁对象 压缩堆 (挂起执行内存托管代码线程:把第0代内存(还不是垃圾的内存)放到一代进行搬迁)释放未标记的对象、搬迁可达对象、修改引用地址
|
||||
|
||||
大对象总被认为是二带内存,目的是减少性能损耗
|
||||
不会对大对象进行压缩搬迁 大对象是85000kb以上的
|
||||
|
||||
示意图
|
||||
step1:程序放入内存
|
||||
![[Pasted image 20260412210327.png|697]]
|
||||
step2:发现沾满了
|
||||
![[Pasted image 20260412210704.png]]
|
||||
step3:原来的地址搬迁,无引用的垃圾丢掉
|
||||
![[Pasted image 20260412210810.png]]
|
||||
step4:D放入
|
||||
![[Pasted image 20260412210946.png]]
|
||||
step5:如果0代1代后续又满了,那么这套算法会同时做用在两代内存中,以此类推
|
||||
类似多级缓存cache,L1最快但常换L3最慢
|
||||
#基础
|
||||
# GC和IDispose()
|
||||
### 首先区分资源类型:
|
||||
|
||||
- **托管资源**:C# 自己管理的内存(比如普通对象、字符串)
|
||||
- 不用你管,**垃圾回收器(GC)会自动释放**
|
||||
- **非托管资源**:C# 管不了的外部资源
|
||||
- 例子:文件流、数据库连接、网络套接字、图片句柄、系统内核对象
|
||||
- **必须手动释放**,否则会造成**资源泄漏**(程序越跑越慢、卡死)
|
||||
|
||||
### 为什么要用 `IDisposable`?
|
||||
|
||||
- 非托管资源 GC 不会自动清理
|
||||
- 必须提供一个**标准、统一**的方式手动释放
|
||||
- `IDisposable` 就是 .NET 专门定义的**释放资源标准接口**
|
||||
|
||||
### 标准释放模式
|
||||
例子:
|
||||
```csharp
|
||||
using System;
|
||||
|
||||
// 1. 实现 IDisposable 接口
|
||||
public class MyResource : IDisposable
|
||||
{
|
||||
// 标记资源是否已释放
|
||||
private bool _disposed = false;
|
||||
|
||||
// 2. 公共释放方法(外部调用)
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
// 告诉GC:不用再管我了,我已经手动释放完了
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// 3. 核心释放逻辑
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
// 释放 托管资源
|
||||
}
|
||||
|
||||
// 释放 非托管资源(比如关闭文件、关闭数据库连接)
|
||||
// 这里写你的资源释放代码
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
// 4. 析构函数:防止用户忘记调用 Dispose
|
||||
~MyResource()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
```
|
||||
##### 解释:
|
||||
逻辑:
|
||||
1. 用完实例化对象
|
||||
2. 调用`.Dispose()`手写的`.Close()`等方法进行手动释放
|
||||
3. 判断标记变量
|
||||
4. 没释放就执行释放代码
|
||||
5. 标记为`true`
|
||||
|
||||
`GC.SuppressFinalize(this);` 的作用
|
||||
告诉.NET的GC这个对象的非托管资源,我**手动释放完了**,你不需要在垃圾回收的时候,再执行它的析构函数了。==它不会取消GC运行,只是取消执行析构函数!==
|
||||
|
||||
|
||||
|
||||
析构函数 `~MyResource()` 是干嘛的?和 GC 啥关系?
|
||||
防止你忘记调用 `Dispose()`
|
||||
场景模拟
|
||||
1. 你写了代码,**马虎忘了**调用 `.Dispose()`
|
||||
2. 非托管资源(文件 / 数据库)一直占着没释放
|
||||
3. 等到 GC(清洁工)来回收垃圾时
|
||||
4. **自动触发析构函数** `~MyResource()`
|
||||
5. 函数里执行 `Dispose(false)`,强行把非托管资源释放了
|
||||
|
||||
|
||||
==一个实例化对象dispose后就不会再用了(设计上就是如此,用过dispose后标签一直是true)==
|
||||
==而且由于它dispose了,内部引用是空的,所以只会留下一个实例化的小壳==
|
||||
==实例化的小壳也会因为没有被引用被GC清理,不会造成太大的性能问题==
|
||||
|
||||
如果需要==一次性==彻底释放
|
||||
例子:
|
||||
```Csharp
|
||||
var resource1 = new MyResource();
|
||||
resource1.Dispose();
|
||||
|
||||
//手动切断引用
|
||||
resource1 = null;
|
||||
//手动触发GC
|
||||
GC.Collection();
|
||||
GC.WaitForPendingFinalizers();//等待回收完成
|
||||
```
|
||||
|
||||
|
||||
#封装
|
||||
#核心
|
||||
@@ -32,3 +32,5 @@ p[0] = new Person();
|
||||
```
|
||||
注意:
|
||||
|
||||
#封装
|
||||
#核心
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# 继承
|
||||
概念:
|
||||
继承是面向对象三大特性之一
|
||||
可以让一个类在已有类的基础上继续扩展
|
||||
被继承的类一般叫==父类 / 基类(base class)==
|
||||
继承别人的类一般叫==子类 / 派生类(derived class)==
|
||||
|
||||
通常用法:
|
||||
1. 提取多个类的共同内容,减少重复代码
|
||||
2. 表达“==is-a==”关系
|
||||
3. 让子类在父类基础上增加自己的成员和功能
|
||||
|
||||
语法:
|
||||
```Csharp
|
||||
class 子类名 : 父类名
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
class Animal
|
||||
{
|
||||
public string name;
|
||||
protected int age;
|
||||
|
||||
public Animal(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void Speak()
|
||||
{
|
||||
cw("动物发出声音");
|
||||
}
|
||||
}
|
||||
|
||||
class Dog : Animal
|
||||
{
|
||||
public Dog(string name, int age) : base(name)
|
||||
{
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public void Bark()
|
||||
{
|
||||
cw(name);
|
||||
cw(age);
|
||||
cw("汪汪");
|
||||
}
|
||||
}
|
||||
|
||||
Dog d = new Dog("旺财", 3);
|
||||
d.Speak();
|
||||
d.Bark();
|
||||
```
|
||||
↑ `Dog : Animal` 就表示 `Dog` 继承了 `Animal`
|
||||
|
||||
注意:
|
||||
1. ==C# 的类只能直接继承一个父类==,也就是单继承
|
||||
2. 继承是可以传递的,A 继承 B,B 继承 C,那么 A 也会继承到 C 的可用成员
|
||||
3. ==构造函数不会被继承==,子类只是可以调用父类构造函数
|
||||
4. 父类的 `private` 成员子类==不能直接访问==,想给子类用一般写 `protected`
|
||||
5. 结构体 `struct` ==不支持继承类==,但可以实现接口
|
||||
6. 子类对象本质上也是父类对象的一种,所以继承是后面学[[多态vob|多态]]的基础
|
||||
|
||||
----
|
||||
# base关键字
|
||||
概念:
|
||||
`base` 用来在==子类内部==访问父类成员
|
||||
最常见的用途就是调用父类构造函数
|
||||
|
||||
通常用法:
|
||||
1. 在子类构造函数中调用父类构造函数
|
||||
2. 在子类方法中访问父类同名成员或父类方法
|
||||
|
||||
语法:
|
||||
```Csharp
|
||||
class Dog : Animal
|
||||
{
|
||||
public Dog(string name) : base(name)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
调用父类成员:
|
||||
```Csharp
|
||||
base.父类成员名
|
||||
```
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
class Father
|
||||
{
|
||||
public string name;
|
||||
|
||||
public Father(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void Say()
|
||||
{
|
||||
cw("我是父类");
|
||||
}
|
||||
}
|
||||
|
||||
class Son : Father
|
||||
{
|
||||
public Son(string name) : base(name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Test()
|
||||
{
|
||||
base.Say();
|
||||
cw(base.name);
|
||||
}
|
||||
}
|
||||
|
||||
Son s = new Son("小李");
|
||||
s.Test();
|
||||
```
|
||||
↑ `base(name)` 是先调用父类构造函数,`base.Say()` 是调用父类方法
|
||||
|
||||
注意:
|
||||
1. `base` 只能在==实例构造函数、实例方法、实例属性访问器==里用
|
||||
2. ==静态方法里不能用 `base`==
|
||||
3. 如果父类没有无参构造函数,子类通常就要显式写 `: base(...)`
|
||||
4. `base` 是访问父类,不是创建一个新的父类对象
|
||||
|
||||
----
|
||||
引用:
|
||||
1. Microsoft Learn: [Inheritance - derive types to create more specialized behavior](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/object-oriented/inheritance)
|
||||
2. Microsoft Learn: [Inheritance in C# and .NET](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/inheritance)
|
||||
3. Microsoft Learn: [base (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/base)
|
||||
4. Microsoft Learn: [protected (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/protected)
|
||||
|
||||
#继承
|
||||
#核心
|
||||
@@ -0,0 +1,86 @@
|
||||
概念:
|
||||
==让自定义类和结构体能够使用运算符==
|
||||
让自定义类结构体可以进行运算
|
||||
通常需要注意运算符需要几个参数,例如取反只有一个参数,加有两个参数
|
||||
可重载的运算符:
|
||||
- 算数运算符
|
||||
- 逻辑运算符==非==
|
||||
- 位运算符
|
||||
- 条件运算符
|
||||
不可重载的运算符:
|
||||
- 逻辑与(&&)逻辑或(||)
|
||||
- 索引符\[]
|
||||
- 墙砖运算符()
|
||||
- 点.
|
||||
- 三目运算符: ?
|
||||
- 赋值符=
|
||||
|
||||
|
||||
通常用法:
|
||||
|
||||
|
||||
语法:
|
||||
使用关键词operator
|
||||
作为类的一个成员存在
|
||||
public static 返回值类型 operator 运算符(参数列表)
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
class Point
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public static Point operator +(Point p1, Point p2)
|
||||
{
|
||||
Point newPoint = new Point();
|
||||
newPoint.x = p1.x + p2.x;
|
||||
newPoint.y = p1.y + p2.y;
|
||||
|
||||
return newPoint;
|
||||
}
|
||||
|
||||
public static Point operator +(Point p1, int value)
|
||||
{
|
||||
Point newPoint = new Point();
|
||||
newPoint.x = p1.x + value;
|
||||
newPoint.y = p1.y + value;
|
||||
return newPoint;
|
||||
}
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Point p1 = new Point();
|
||||
p1.x = 1;
|
||||
p1.y = 1;
|
||||
|
||||
Point p2 = new Point();
|
||||
p2.x = 2;
|
||||
p2.y = 2;
|
||||
|
||||
Point p3 = new Point();
|
||||
p3 = p1 + p2;
|
||||
Console.WriteLine(p3.x);
|
||||
|
||||
p3 = null;
|
||||
p3 = p1 + 10;
|
||||
Console.WriteLine(p3.x);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
第一个运算符重载了`+`号,可以让这个类的两个实例化对象相加
|
||||
第二个运算符也重载了`+`号,可以让这个类加上一个value
|
||||
==如果需要value在前也需要进行一次重载!!!==
|
||||
|
||||
|
||||
注意:
|
||||
1. 一定是公共的静态方法
|
||||
2. 返回值写在operator前
|
||||
3. 逻辑处理自定义
|
||||
4. 一个符号可以多个重载
|
||||
5. 不能使用ref和out
|
||||
6. ==条件运算符需要成对实现==
|
||||
@@ -0,0 +1,51 @@
|
||||
概念:
|
||||
用static 修饰的成员变量、方法、属性
|
||||
|
||||
特点:
|
||||
==直接用类名点出来使用 没有实例化!!!!==
|
||||
|
||||
通常用法:
|
||||
PI之类的全局且唯一性的
|
||||
|
||||
语法:
|
||||
static 变量名 = XXX;
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
class Test
|
||||
{
|
||||
static public float PI = 3.1415926; //静态成员
|
||||
public int testInt = 100;
|
||||
|
||||
public static float CalcCircle(float r) //静态方法
|
||||
{
|
||||
return PI * r;
|
||||
}
|
||||
|
||||
public void TestFunc() //非静态方法
|
||||
{
|
||||
Console.WriteLine("123");
|
||||
}
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine(Test.PI);
|
||||
Console.WriteLine(Test.CalcCircle(2));
|
||||
}
|
||||
```
|
||||
|
||||
注意:
|
||||
和程序同生共死,在程序使用后永远不会清除内存,直到程序结束
|
||||
非静态函数可以调用静态成员
|
||||
静态成员声明后可以不赋初始值
|
||||
静态方法中不能使用==没有实例化的==非静态成员
|
||||
|
||||
|
||||
[[常量]]可以理解为特殊的静态
|
||||
共同点
|
||||
- 都可以通过类名点出来使用
|
||||
不同点
|
||||
- const必须初始化,不能修改 static 没有这个限制
|
||||
- const值能修饰变量、static可以修饰很多
|
||||
- const一定是写在访问修饰符后面的,static没有这个要求
|
||||
@@ -0,0 +1,70 @@
|
||||
# 静态类
|
||||
概念:
|
||||
用static修饰
|
||||
==只能包含静态成员==
|
||||
==不能被实例化==
|
||||
|
||||
通常用法:
|
||||
作为==工具类==方便使用
|
||||
|
||||
语法:
|
||||
访问修饰符 static 类名(){}
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
public static class fun()
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
注意:
|
||||
静态类不能被实例化,所以不能new!
|
||||
|
||||
# 静态构造函数
|
||||
概念:
|
||||
staitc修饰
|
||||
|
||||
通常用法:
|
||||
在静态函数中初始化静态变量
|
||||
|
||||
语法:
|
||||
|
||||
|
||||
案例:
|
||||
```Csharp
|
||||
static class StaticClass
|
||||
{
|
||||
public static int testInt = 100;
|
||||
public static int testInt2 = 100;
|
||||
|
||||
static StaticClass()
|
||||
{
|
||||
Console.WriteLine("静态构造函数");
|
||||
}
|
||||
}
|
||||
```
|
||||
↑运行后,在第一次使用该类会直接打印
|
||||
```Csharp
|
||||
class Test
|
||||
{
|
||||
public static int testInt = 200;
|
||||
|
||||
static Test()
|
||||
{
|
||||
Console.WriteLine("静态构造函数");
|
||||
}
|
||||
|
||||
|
||||
public Test()
|
||||
{
|
||||
Console.WriteLine("普通构造函数");
|
||||
}
|
||||
}
|
||||
```
|
||||
↑运行后,在第一次使用该类会在所有操作前先调用静态构造函数
|
||||
注意:
|
||||
1. 静态类和普通类都可以用
|
||||
2. 不能使用访问修饰符
|
||||
3. ==不能有参数==
|
||||
4. 只会==自动调用一次==
|
||||
Reference in New Issue
Block a user