本篇总结一些 C# 4.0 - 7.0的语法特性。 如今都是距离5.xUnity盛行的时代都过去两年多了,该看一看新语法不然要落伍啦。

UNITY版本与C#版本关系
Unity 5.5.4 自带的Mono也可以支持C# 6,在mcs.rsp文件中添加一行:-langversion:6即可。
Unity 2017.1 C# 6.0 试验性地支持新脚本运行时。This includes Mono 4.8 and IL2CPP with support for C# 6 and .NET 4.6
Unity 2018.1 C# 7.2

总的来说新特性还是在2018的运行环境下比较稳定,所以建议在2018下再去放开使用。下面列出的特性基本上都可以在2018中使用。不能使用的部分已经做了标注,下面是正文:

比较重要的一些特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
using System;
//---------静态引用,下面用到此命名空间下的函数可以直接调用----------
using static System.Console;

namespace Test1
{

internal class Program
{
public Random random;

public int Level { get; set; } = 1_000_000;

public int Hp => ++Level;

public static void Main(string[] args)
{
var p = new Program();

//------------新属性赋值--------------
for (int i = 0; i < 3; i++)
{
p.PrintLog(p.Hp);
// 运行结果:
// 1000001
// 1000002
// 1000003
}


//------------新异常条件与$字符串拼接--------------
try
{
throw new Exception("Test Expection");
}
catch (Exception e) when (p.Hp == 1000004) //新增条件设置 可以制定捕捉异常的条件
{
WriteLine
(
string.Format($"当前信息{e.Message},hp为{p.Hp}") //使用$符号即可使用花括号自定义拼接
);
}


//------------?.空指判断--------------
p.PrintLog(p.random?.Next(0,10));//这行代码并不会执行 因为 random为null ,使用 ?. 来控制当前函数是否执行


//-------------下面两行是等价的,您可以使用下划线代替参数传入,相应也获取不到变更对象-----------------
//p.PrintObject(out var test_p); 现在可以直接在括号内定义一个想要传入的参数
p.PrintObject(out _);


//-------局部函数----------
PrintLog("直接调用下面的局部函数,使用局部函数优于使用lambda"); //局部函数并未有代码行数上的优先级
void PrintLog(string content) => WriteLine(content);

//-------使用return ref 减小开销----------
// PrintLog(p.Avg(1,2).ToString());


}

// 使用 ref 减少值类型的复制 在 C#7.3中实现
// public ref float Avg(int a, int b)
// {
// float _avg = (a + b) / 2.0f;
// return ref _avg;
// }



public void PrintObject(out object obj)
{
obj = new Program();
WriteLine(nameof(obj)); // 使用 nameof 系统关键字来或者当前变量名
}

//简略定义函数
public void PrintLog(int? content) => WriteLine(content); //静态引用 System.Console 命名空间,直接调用 Console.WriteLine 简写为 WriteLine
}
}

#元组分开列一下
元组和Lua,python,swift里的元组几乎大同小异。但是作为C#的最最重要的新工具还是着重测试一下。主要代码您可以直接参考下面列出的类,其中有一点没有描述,就是关于元组== 运算符 的计算,他是从左到右依次比对的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;

namespace Test1
{
internal class Program
{
public static void Main(string[] args)
{
//-----元组的默认定义与访问方式--------
var tuple_2 = ("content1","content2");
Console.WriteLine(tuple_2.Item1 + tuple_2.Item2);

//同样的也可以像给变量起名一般自己定一个"变量名"
var tuple_1 = (str1 : "content1",str2 : "content2");
Console.WriteLine(tuple_1.str1 + tuple_1.str2);

//元组可以直接由函数返回
var method_1 = Program.MethodTest();
Console.WriteLine(method_1.a + method_1.b);

//-----元组的解构-------
var testCls = new MyClass{ A = 1,B = 2,C = 3};
var(args1, args2, args3) = testCls;
Console.WriteLine($"当前args1:{args1},args2:{args2},args3:{args3}");

//元组解构的优先级默认如果本类中有实现则执行本类内部实现,如果没有则执行外部,如扩展函数
}

static (int a, int b) MethodTest()
{
var t = (1,2);
return t;
}
}

public class MyClass
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }

// public void Deconstruct(out int a,out int b,out int c)
// {
// a = A;
// b = B;
// c = C;
// }
}

public static class Extension4Tuple{
public static void Deconstruct(this MyClass cls, out int a, out int b, out int c)
{
a = 10;
b = 11;
c = 12;
}
}
}

参考资料

微软文档