[Unity脚本运行时更新]C#7.2新特性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhenghongzhi6/article/details/83055293

洪流学堂,让你快人几步!本文首发于洪流学堂微信公众号。

本文是该系列《Unity脚本运行时更新带来了什么?》的第7篇。
洪流学堂公众号回复runtime,获取本系列所有文章。

Unity2017-2018.2中的4.x运行时已经支持到C#6,之前的文章已经介绍完毕。Unity2018.3将支持到C# 7.3,今天我们来看看C#7.2新特性能给代码带来什么吧,不过这些特性得等到Unity2018.3才可以用哦

C#7.2 新特性

C#7.2的一项主要功能是避免不必要的复制或内存分配,进而更有效地处理值类型。

值类型的引用语法

在C# 7.2中,值类型的引用语法做了优化,旨在尽量减少值类型的拷贝、内存分配,进而提升性能。 功能包括:

  • 添加实参的 in 修饰符:指定形参通过引用传递,但不会在调用的方法中修改。新增的参数 in 修饰符是源兼容的更改

源兼容的更改
如果使用库的应用程序和库不需要更改源代码,但必须根据新版本重新编译源才能正常工作,那么对库的更改属于源兼容的更改。

  • 针对方法返回值的 ref readonly 修饰符:指示方法通过引用返回其值,但不允许写入该对象。 如果向某个值赋予返回值,则添加 ref readonly 修饰符是源兼容的更改。 将 readonly 修饰符添加到现有的 ref 返回语句是不兼容的更改。 需要调用方更新 ref 本地变量的声明以包含 readonly 修饰符。

不兼容的更改
如果更改既不是源兼容的更改,也不是二进制兼容的更改,则需要在从属库和应用程序中进行源代码更改和重新编译。

  • readonly struct 声明,指示结构不可变,且应作为 in 参数传递到其成员方法。 将 readonly 修饰符添加到现有的结构声明是二进制兼容的更改

二进制兼容的更改
如果更新的库可以在不重新生成应用程序和使用它的库的情况下使用,那么对库的更改属于二进制兼容的更改。 不需要重新生成从属程序集,也不需要更改任何源代码。 二进制兼容的更改也是源兼容的更改。

  • ref struct 声明,指示结构类型直接访问托管的内存,且必须始终分配有堆栈。 将 ref 修饰符添加到现有 struct 声明是不兼容的更改。 ref struct 不能是类的成员,也不能用于可能在堆上分配的其他位置。

更多细节可以查阅:https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/readonly-ref.md

条件ref

C# 7.2之前,ref变量无法通过条件表达式来返回。通常的变通方案是通过方法:

ref T Choice(bool condition, ref T consequence, ref T alternative)
{
    if (condition)
    {
         return ref consequence;
    }
    else
    {
         return ref alternative;
    }
}

但是这样写其实是有问题的:

ref var r = ref Choice(arr != null, ref arr[0], ref otherArr[0]);

如果arr为空,arr[0]在传入时会引发异常。

新的功能如下:

<condition> ? ref <consequence> : ref <alternative>;

实现上面的功能的代码类似:

ref var r = ref (arr != null ? ref arr[0]: ref otherArr[0]);

条件ref既可以作为右值,也可以作为左值,常见的用法有:

// pass by reference
foo(ref (arr != null ? ref arr[0]: ref otherArr[0]));

// return by reference
return ref (arr != null ? ref arr[0]: ref otherArr[0]);

// assign to
(arr != null ? ref arr[0]: ref otherArr[0]) = 1;

int x = (arr != null ? ref arr[0]: ref otherArr[0]);

不在尾部的指定名字参数

从C# 7.2开始,指定名字的参数可以不在尾部位置,只要他们的位置是正确的。比如:DoSomething(isEmployed:true, name, age);

更多例子如:

public void DoSomething(bool isEmployed, string personName, int personAge) { ... }

DoSomething(isEmployed:true, name, age); // CS7.2后编译通过
DoSomething(true, personName:name, age); // CS7.2后编译通过
DoSomething(name, isEmployed:true, age); // 非法
DoSomething(name, age, isEmployed:true); // 非法
DoSomething(true, personAge:age, personName:name); // 之前已经可以编译通过

数值字面值的下划线

C# 7.0 中实现了对数字分隔符的支持,但这不允许文字值的第一个字符是 _。 C# 7.2之后,十六进制文本和二进制文本可以 _ 开头。

例如:

int binaryValue = 0b_0101_0101;

private protected 访问修饰符

新的复合访问修饰符 private protected 指示可通过包含同一程序集中声明的类或派生类来访问成员。 虽然 protected internal 允许通过同一程序集中的类或派生类进行访问,但 private protected 限制对同一程序集中声明的派生类的访问。

小结

本文讲解了C#7.2的新特性中对Unity编程有影响的新特性,不过这些特性得等到Unity2018.3才可以用哦

洪流学堂公众号回复runtime,获取本系列所有文章。

把今天的内容分享给其他Unity开发者朋友,或许你能帮到他。



《郑洪智的Unity2018课》,倾尽我8年的开发经验,结合最新的Unity2018,带你从入门到精通。

猜你喜欢

转载自blog.csdn.net/zhenghongzhi6/article/details/83055293