Article Directory
Note: Only some functions and features that will be used in Unity development are mentioned here, and the content that is not suitable for use in Unity will be ignored.
C# 8 corresponds to the Unity version:
- Unity 2020.3 —— C# 8
However, some new content is not yet supported in this version of Unity, and some more practical content is screened below.
C# 8 new features and syntax:
- Using statement
- static local function
- Null coalescing assignment
- Deconstruct function Deconstruct
- Pattern Matching Enhancements
1. Using statement
The Using statement is a shorthand for the using syntax. When the function is executed, the Dispose method of the object will be called to release the object.
public class Lesson10 : MonoBehaviour
{
void Start() {
using StreamWriter s2 = new StreamWriter("文件路径");
// 对该对象进行逻辑操作
s2.Write(5);
s2.Flush();
s2.Close();
// 利用这个写法 就会在上层语句块执行结束时释放该对象
}
}
Note: When using the using syntax, the declared object must inherit the System.IDisposable interface:
public class TestUsing : IDisposable
{
public void Dispose() {
}
}
public class Lesson10 : MonoBehaviour
{
void Start() {
using TestUsing t = new TestUsing();
}
}
Because the Dispose method must be available, an error will be reported when declaring an object that does not inherit this interface.
2. Static local functions
A static local function is to add the static keyword in front of the local function.
Role: Make local functions unable to use and access any variables in the closed scope (that is, in the upper-level method), so that local functions can only process logic, and avoid making it process logic by directly changing upper-level variables to cause logic confusion.
public int TestTst(int i) {
bool b = false;
i += 10;
Calc(ref i, ref b); // 执行静态本地函数
return i;
// 静态本地函数
static void Calc(ref int i, ref bool b) {
i += 10;
b = true;
}
}
3. Null merge assignment
Null coalescing assignment is a newly added operator in C# 8.0 ??=
, similar to the composite operator:
When左边值 ??= 右边值
the left side is empty, the value on the right side is assigned to the variable.
Example:
string str = null;
str ??= "4565";
print(str); // "4565"
// 注意:由于左侧为空才会讲右侧赋值给变量,所以不为空的变量不会改变
str ??= "1111";
print(str); // "4565"
Fourth, the deconstructing function Deconstruct
We can declare the deconstruction function in the custom class, so that we can use the tuple writing method to obtain the variable of the custom class object.
Syntax: Declare a function inside a class:
Featurespublic void Deconstruct(out 变量类型 变量名, out 变量类型 变量名.....)
: There can be multiple Deconstructs in a class, but the number of parameters cannot be the same.
public class Person
{
public string name;
public bool sex;
public string number;
public string email;
// 三个解构函数
public void Deconstruct(out string n, out bool sex) {
n = name;
sex = this.sex;
}
public void Deconstruct(out string n, out bool sex, out string number) {
n = name;
sex = this.sex;
number = this.number;
}
public void Deconstruct(out string n, out bool sex, out string number, out string email) {
n = name;
sex = this.sex;
number = this.number;
email = this.email;
}
}
public class Lesson10 : MonoBehaviour
{
void Start() {
// 初始化并赋值
Person p = new Person();
p.name = "xxx";
p.sex = false;
p.number = "123123123123";
p.email = "[email protected]";
// 对该对象利用元组将其具体的变量值解构出来
// 相当于把不同的成员变量拆分到不同的临时变量中
(string name, bool sex) = p;
print(name); // "xxx"
print(sex); // "false"
string str3;
(_, _, str3) = p;
print(str3); // "123123123123"
}
}
The destructor function can also be abbreviated as:
public void Deconstruct(out string n, out bool sex) => (n, sex) = (this.name, this.sex);
public void Deconstruct(out string n, out bool sex, out string number) => (n, sex, number) = (this.name, this.sex, this.number);
public void Deconstruct(out string n, out bool sex, out string number, out string email) => (n, sex, number, email) = (this.name, this.sex, this.number, this.email);
5. Pattern matching enhancements
In C# 7, there are already three types of pattern matching: constant pattern, type pattern and var pattern. In C# 8, the following patterns are newly added:
- switch expression
- attribute mode
- tuple pattern
- location mode
(1) switch expression
For the following enumerations:
public enum PosType
{
Top_Left,
Top_Right,
Bottom_Left,
Bottom_Right,
}
When you need to write a function to get the corresponding position, use switch to write as follows:
public Vector2 GetPos(PosType type) {
switch (type) {
case PosType.Top_Left:
return new Vector2(0, 0);
case PosType.Top_Right:
return new Vector2(1, 0);
case PosType.Bottom_Left:
return new Vector2(0, 1);
case PosType.Bottom_Right:
return new Vector2(1, 1);
default:
return new Vector2(0, 0);
}
}
A switch expression is an abbreviation for a switch statement that returns a value:
- Use
=>
expression symbols instead ofcase:
combinations - Use
_
the discard symbol insteaddefault:
Its usage restrictions are mainly used when there is only one line of code in the switch statement for the return value:
public Vector2 GetPos(PosType type) => type switch {
PosType.Top_Left => new Vector2(0, 0),
PosType.Top_Right => new Vector2(1, 0),
PosType.Bottom_Left => new Vector2(0, 1),
PosType.Bottom_Right => new Vector2(1, 1),
_ => new Vector2(0, 0)
};
(2) Attribute mode
That is, judge each attribute on the object on the basis of the constant mode.
Usage: 变量 is {属性:值, 属性:值}
.
For the following discount categories:
public class DiscountInfo
{
public string discount;
public bool isDiscount;
public DiscountInfo(string discount, bool isDiscount) {
this.discount = discount;
this.isDiscount = isDiscount;
}
public void Deconstruct(out string dis, out bool isDis) {
dis = this.discount;
isDis = this.isDiscount;
}
}
If you need to judge its specific information, you need to obtain the values of its two member variables for judgment:
DiscountInfo info = new DiscountInfo("5折", true);
if( info.discount == "6折" && info.isDiscount)
print("信息相同");
Use the attribute mode to quickly judge:
if (info is {
discount: "6折", isDiscount: true })
print("信息相同");
Combined with switch expression:
public float GetMoney(DiscountInfo info, float money) => info switch {
// 属性模式结合 switch 表达式判断 n 个条件是否满足
{
discount: "5折", isDiscount: true } => money * .5f,
{
discount: "6折", isDiscount: true } => money * .6f,
{
discount: "7折", isDiscount: true } => money * .7f,
_ => money
};
(3) Tuple mode
The tuple mode does not need to declare the data structure class, and can directly use the tuple to judge:
int ii = 10;
bool bb = true;
if ((ii, bb) is (11, true)) {
print("元组的值相同");
}
public float GetMoney(string discount, bool isDiscount, float money) => (discount, isDiscount) switch {
("5折", true) => money * .5f,
("6折", true) => money * .6f,
("7折", true) => money * .7f,
_ => money
};
(4) Position mode
If the deconstruction function is implemented in the custom class, you can directly use the corresponding class object and tuple to judge is:
if (info is ("5折", true)) {
print("位置模式 满足条件");
}
At the same time, it can also cooperate with the when keyword for logical processing:
public float GetMoney2(DiscountInfo info, float money) => info switch {
("5折", true) when money > 100 => money * .5f,
("6折", true) => money * .6f,
("7折", true) => money * .7f,
_ => money
};