1.C# 可空类型(Nullable)
?? 左边不为空返回左边 反之 返回右边
2.c#中ref和out
1、使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。
2、使用ref和out时,在方法的参数和执行方法时,都要加显示的加Ref或Out关键字。以满足匹配。
3、out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。
转自C#中out和ref之间的区别 - 石shi - 博客园 (cnblogs.com)
3.交错数组
4.值类型和引用类型
值类型 它变我不变
引用类型 它变我也变
5.string
string虽然是引用类型 却有着它变我不变的值类型特性
这一特性在代码中体现的是 如果赋值后不使用 没有销毁 就会产生内存垃圾
优化: 用StringBulider
6.变长参数 params
7.函数重载
参数的顺序不同也属于
8.const和static
8.索引器
9.变量类型及大小
10.转义字符
\' 输出' \'' \n \\ \t制表符 \b光标退格 \a \0
11.显示转换的几种方式
1.()强转
2.Parse 字符串转其他 如 int.Parse(1.2)
3.Convert 任意类型转
4.Tostring 转
12.异常捕获
try{}里的语句报错 catch{}捕获
13.秒转天时分秒
14.位运算
35<<4 64>>1
二进制=>左移几位 末尾加几个0 ;右移几位 倒叙删除末尾几位=>转十进制输出
15.字符串内插 和=>运算符
字符串内插 $ 可以直接打印变量
=>运算符主要用在
16.反射
1.Type:类的信息类,得到对象的类型,用于获取元数据。
(1)三种方式可以获取type:变量的GetType()方法 、typeof(类名)、Type.GetType("类的命名空间+类名")
三种方法得到的type的值都是一样的,不同的栈位置,但是都是指向同一个堆。
(2)得到的三类信息:ConstructorInfo:所有构造函数信息,MemberInfo:所有公共函数的信息,FieldInfo:所有公共变量的信息。可以单个获取(传名字),也可以全部获取。
(3)函数参数相关
函数有几个参数: Type
函数传参数: object
例如:
MethodInfo method = T.GetMethod("add",new Type[] { typeof(int), typeof(string) });(函数如果是static的话,第一个参数传null即可 无参是Type【0】)
method.Invoke(T,new object[]{ 2,"ccc"});
2.Assembly 得到程序集信息
Assembly.Load 同项目文件
Assembly.LoadForm("dll文件路径") 不同项目文件(找不到路径,看看两个项目的.Net框架是否一致,不同就会报错)
3.Activator 快速得到对象
Activator.CreateInstance(type);
17.类内变量初始化规则
继承了一个类,初始化变量时,不能用非静态字段初始化,但是可以访问父类中公有,保护声明相关的变量和方法。
18.override和new
在 C# 中,隐藏(Hide)父类方法通常使用关键字 new
,而重写(Override)父类虚方法则使用 virtual
关键字。两者的主要区别在于:
-
隐藏(Hide):
- 当子类使用
new
关键字重写父类的方法时,子类对象调用的是子类版本的方法,而不是父类的方法。父类中被new
修饰的方法在子类中不会被访问,除非特别指定去调用父类的同名方法。 - 子类对象不知道它有一个隐藏的父类方法,因此在代码中通常不推荐直接使用
new
来隐藏方法,因为它可能导致意料之外的行为。
- 当子类使用
-
重写(Override):
- 使用
virtual
关键字声明的方法在子类中可以被重写。这意味着子类可以提供自己版本的实现,当子类对象调用该方法时,会执行子类的方法。 virtual
关键字还用于标识一个方法为虚函数(Virtual Function),这是实现多态的基础,因为它允许子类改变父类的行为。- 如果子类没有提供自己的实现,那么在运行时会默认调用父类的方法,这称为隐式虚拟调用(Implicit Virtual Call)。
- 使用
19.泛型中的new()
进阶:
可选参数
可以指定函数参数的赋值,不用按顺序来。同时方便对已经初始化的参数进行赋值操作。
dynamic 动态类型
使用前要修改unity的API的适用版本选2.1的另外一个
线程池
一些API 获取可用工作线程 io线程数 最大 最小数 开启线程(方法中有两个参数,如果传了第二个参数,它就是第一个参数的值)
//得到可用工作线程数和IO线程数
ThreadPool.GetAvailableThreads(out num1,out num2);
Debug.Log(num1);
Debug.Log(num2);
//设置
ThreadPool.SetMaxThreads(20, 20);
//最大线程 io
ThreadPool.GetMaxThreads(out num3, out num4);
Debug.Log(num3);
Debug.Log(num4);
if(ThreadPool.SetMinThreads(5,5))
{
Debug.Log("设置成功");
}
ThreadPool.GetMinThreads(out num5, out num6);
Debug.Log(num5);
Debug.Log(num6);
ThreadPool.QueueUserWorkItem((obj) =>
{
Debug.Log("开启了一个线程:" + obj);
}, "dadada");
Task
异步方法Async和Await
ref和out不能使用 是因为要返回 而异步有时候还没执行完需要直接到主线程 会报错
private void Start()
{
TestAsync(this.gameObject);
}
public async void TestAsync(GameObject obj)
{
// 1
print("123");
// 2 函数执行到这一步的时候 控制权返回给了主线程
// 异步方法被挂起 等到下面这个Task结束之后
// 执行 3之后的代码
await Task.Run(() =>
{
Thread.Sleep(3000);
});
// 3
this.gameObject.transform.position=Vector3.zero;
print("线程结束对象位置改变了");
}
静态导入、异常筛选器、 nameof运算符
静态导入就是在 头文件 using xxx xxx写需要导入静态的名字 就不需要 .出来使用了
直接可以对一些方法类使用 比如using System.MathF,也可以对自己定义的类使用
异常筛选器 就是catch后面加个 when(条件) 满足的才进catch语句。可以有多个
nameof运算符 得到变量或者函数名
out变量快捷使用和弃元、ref变引用、本地函数
out变量快捷使用 就是out参数传递事前可以不用声明变量了 直接在out参数上声明
弃元 比如两个out参数返回 只想得到第一个 第二个就写成 out_
ref变引用 就是值类型改值不改本值的那一套变为了引用类型的那套 可以改值了 可以用于变量、返回值...之间
本地函数 就是函数里面还有函数的定义
元组
无变量名元组的声明 和有变量名元组的声明
函数返回值
元组的应用--字典
模式匹配
常量模式
类型模式(Switch)
这里 value的值和o一样的
using声明、Null合并赋值、解构函数Deconstruct
??= 左边为空就把右边赋值给左边 否则不变
解构函数Deconstruct:
类里声明的一个public函数
外部可以直接用元组去接 元组值就是类的变量值