1. 程式人生 > >[Unity指令碼執行時更新]C#7.2新特性

[Unity指令碼執行時更新]C#7.2新特性

洪流學堂,讓你快人幾步!本文首發於洪流學堂微信公眾號。

本文是該系列《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,帶你從入門到精通。