一.C# 1~4的一些新功能
1.命名参数:
void Start()
{
//命名参数可以实现打乱参数顺序,使用[参数名:]指定参数
Test01(b: 2, c: 1, a: 0);
//命名参数一般使用于有多个默认值的参数的情况
Test02(1, p: 3);
}
private void Test01(int a, int b, int c)
{
}
private void Test02(int m , int n = 2, int p = 3, int q = 4)
{
}
2.动态类型
void Start()
{
//动态类型dynamic,这个类型在运行时检查类型
//和var不同,var在编译时检查类型,也就是说,虽然我们写的是var类型,但是在编译时实际类型是明确的,编辑器中鼠标指到var上也能显示实际类型,而dynamic类型在编译时实际类型不明确,鼠标指到dynamic上不会显示实际类型
//dynamic类型在编译时会编译为object类型,但是在代码中可以点出各种方法(和object的区别在于,dynamic可以是任意类型,并可以直接调用这个类型的所有方法,object类型需要转型)
//dynamic类型可以用于替换反射操作
dynamic a = 1;
var b = 1;
a.Test01(1, 2);//编辑器中并不会报错
}
private void Test01(int a, int b, int c)
{
}
二.C# 5的一些新功能
1.Task任务类
void Start()
{
//简介:Task是对线程的封装,以便更为方便地管理线程,一个task就是一个线程
//创建task
//方法一:直接new一个Task,需要传入线程执行地委托
Task task01 = new Task(Test01);
task01.Start();
//方法二:使用静态方法Run创建task并直接开启
var task02 = Task.Run(Test01);
//方法三:使用Factory创建并直接开启
var task03 = Task.Factory.StartNew(Test01);
//说明:以上三种方式都可以通过泛型指定返回值,创建有返回值的task
var task04 = Task.Run<int>(Test02);
//通过Result获取返回值
print(task04.Result);//注意:通过Result获取返回值时,如果此时task还没有执行得到返回值,主线程会阻塞等待task执行直到得到返回值;如果这时task是一个死循环,主线程会卡死
//同步执行task
//使用new创建的task可以同步执行
var task05 = new Task(Test01);
task05.RunSynchronously();//使用RunSynchronously方法同步执行线程,这种方式执行的线程主线程会等待其执行完毕再继续执行,和在主线程中执行代码类似
//阻塞执行task
var task06 = Task.Run(Test01);
task06.Wait();//这个方法会让主线程在等待task06的逻辑执行完毕后再执行之后的代码
Task.WaitAny(task01, task02, task03, task04, task05, task06);//这个方法会让主线程在等待传入的task中的任意一个任务完成后继续执行之后的代码
Task.WaitAll(task01, task02, task03, task04, task05, task06);//这个方法会让主线程在等待传入的所有task都执行完成后再继续执行之后的代码
}
private void Test01()
{
}
private int Test02()
{
return 1;
}
2.异步方法Async和await
//在方法名前使用async关键字标识这是一个异步方法
//使用async修饰的函数中可以没有await关键字
//异步方法名称建议以Async结尾
//异步方法的返回值只能是void或者task
//异步方法的变量不能使用ref或者out修饰
private async void TestAsync()
{
//await经常和task配合使用
//await可以开启一个新线程,并挂起异步方法,将控制权返回给调用者,等待开启的新线程逻辑执行完毕之后继续执行当前异步方法
await Task.Run(
() =>
{
print($"新线程逻辑执行,当前时间:{Time.time}");
Thread.Sleep(1000);
});
print($"异步方法执行完毕,当前时间:{Time.time}");
}
void Start()
{
TestAsync();
}
三.C# 6的一些新功能
1.静态导入
using UnityEngine;
//引用命名空间时,使用静态导入,之后可以直接访问其静态成员
using static UnityEngine.Mathf;
public class Test1 : MonoBehaviour
{
void Start()
{
//静态导入了Mathf类后,可以直接不用指明类名就可以使用其中的方法
Clamp01(0.5f);
}
}
2.异常筛选器
void Start()
{
try
{
}
//使用when关键字对捕获到的异常进行限制
catch (Exception e) when (e.Message.Contains("301"))
{
}
catch (Exception e) when (e.Message.Contains("404"))
{
}
//最后一个catch可以不加when关键字进行筛选,意为使用默认方式处理剩余的异常
catch (Exception e)
{
}
finally
{
}
}
3.nameof关键字
void Start()
{
int i = 0;
//使用nameof关键字直接得到变量类型名称
print(nameof(i));
//也可以得到方法名
print(nameof(List<int>.Add));
//可以得到类名
print(nameof(List<int>));
}
四.C# 7的一些新功能
1.字面值改进
void Start()
{
//在字面值上添加_作为分隔符方便阅读
int i = 1_2345_6789;
}
2.out的快捷使用
void Start()
{
//在使用out参数时可以直接在给定参数的同时声明变量
if(TryGetInt32(out var num))
{
print(num);
}
}
private bool TryGetInt32(out int num)
{
num = 1;
return true;
}
3.弃元
void Start()
{
//使用_替换不想使用的out参数
if(TryGetInt32(out _))
{
print("");
}
}
private bool TryGetInt32(out int num)
{
num = 1;
return true;
}
4.ref关键字将值类型改为引用类型
void Start()
{
//使用ref关键字将值类型改为引用类型
int i = 100;//值类型i
ref int j = ref i;//引用类型j
}
5.本地函数
void Start()
{
//直接使用本地函数
int i = 0;
Test();
//本地函数,即函数中声明的函数,可以使用原函数中的所有局部变量
void Test()
{
print(i);
}
}
6.元组
void Start()
{
//使用括号将多个变量组合成一个元组(相当于一个简单的结构体)
(int, float, bool) i = (1, 2f, true);
//使用item1\item2\item3...取用元组中的内容
print($"{i.Item1}|{i.Item2}|{i.Item3}");
//可以给元组中的元素取别名
(int num, float time, bool health) j = (1, 2f, false);
//使用别名取用
print($"{j.num}|{j.time}|{j.health}");
}
7.模式匹配
void Start()
{
//常量模式:[is 常量]用于判断是否是某个值
int i = 1;
if(i is 1)
{
print(i);
}
//类型模式:[is 类型名 变量名]用于判断变量是否是某个类型,是的话同时将其转型为新类型
object j = 2;
if(j is int k)
{
print(k);
}
//类型模式和switch语句的配合
switch (j)
{
case int m:
print(nameof(Int32));
break;
case float n:
print(nameof(Single));
break;
case bool b:
print(nameof(Boolean));
break;
default:
print("");
break;
}
//var模式:[is var 变量名]相当于将变量转存
bool d = true;
if(d is var e)
{
print(e.GetType().Name);
}
}