C# 7.3 版本有兩個主要主題。 第一個主題提供使安全代碼的性能與不安全代碼的性能同樣好的功能。 第二個主題提供對現有功能的增量改進。 此外,在此版本中添加了新的編譯器選項。html
如下新增功能支持使安全代碼得到更好的性能的主題:編程
ref
本地變量。stackalloc
數組上的初始值設定項。fixed
語句。對現有功能進行了如下加強:api
==
和 !=
。in
區分的參數的方法解析獲得了改進。新的編譯器選項爲:數組
-publicsign
,用於啓用程序集的開放源代碼軟件 (OSS) 簽名。-pathmap
用於提供源目錄的映射。
你應可以安全地編寫性能與不安全代碼同樣好的 C# 代碼。 安全代碼可避免錯誤類,例如緩衝區溢出、雜散指針和其餘內存訪問錯誤。 這些新功能擴展了可驗證安全代碼的功能。努力使用安全結構編寫更多代碼。 這些功能使其更容易實現。安全
unsafe struct S { public fixed int myFixedField[10]; }
在早期版本的 C# 中,須要固定變量才能訪問屬於 myFixedField
的整數之一。 如今,如下代碼進行編譯,而不將變量 p
固定到單獨的 fixed
語句中:ide
class C { static S s = new S(); unsafe public void M() { int p = s.myFixedField[5]; } }
變量 p
訪問 myFixedField
中的一個元素。 無需聲明單獨的 int*
變量。 請注意,你仍然須要 unsafe
上下文。 在早期版本的 C# 中,須要聲明第二個固定的指針:函數
class C { static S s = new S(); unsafe public void M() { fixed (int* ptr = s.myFixedField) { int p = ptr[5]; } } }
有關詳細信息,請參閱有關 fixed
語句的文章。性能
ref
局部變量進行初始化後,可能會對其從新分配,以引用不一樣的實例。 如下代碼如今編譯:
ref VeryLargeStruct refLocal = ref veryLargeStruct; // 初始化 refLocal = ref anotherVeryLargeStruct; // 從新分配後,反射引用不一樣的存儲。
有關詳細信息,請參閱有關 ref
返回和 ref
局部變量以及 foreach
的文章。測試
var arr = new int[3] {1, 2, 3}; var arr2 = new int[] {1, 2, 3};
如今,可向使用 stackalloc
進行聲明的數組應用同一語法:ui
int* pArr = stackalloc int[3] {1, 2, 3}; int* pArr2 = stackalloc int[] {1, 2, 3}; Span<int> arr = stackalloc [] {1, 2, 3};
有關詳細信息,請參閱stackalloc
運算符一文。
fixed
語句支持有限的一組類型。 從 C# 7.3 開始,任何包含返回 ref T
或 ref readonly T
的 GetPinnableReference()
方法的類型均有可能爲 fixed
。 添加此功能意味着 fixed
可與 System.Span<T> 和相關類型配合使用。
有關詳細信息,請參閱語言參考中的 fixed
語句一文。
如今,能夠將類型 System.Enum 或 System.Delegate 指定爲類型參數的基類約束。
如今也能夠使用新的 unmanaged
約束來指定類型參數必須爲「非託管類型」 。 「非託管類型」 不是引用類型,且在任何嵌套級別都不包含任何引用類型。
有關詳細信息,請參閱有關 where
泛型約束和類型參數的約束的文章。
將這些約束添加到現有類型是不兼容的更改。 封閉式泛型類型可能再也不知足這些新約束的要求。
如下功能提供了對語言中的功能的改進。 這些功能提高了在編寫 C# 時的效率。
[field: SomeThingAboutFieldAttribute] public int SomeProperty { get; set; }
屬性 SomeThingAboutFieldAttribute
應用於編譯器生成的 SomeProperty
的支持字段。 有關詳細信息,請參閱 C# 編程指南中的屬性。
in
參數修飾符時,這兩個方法將致使多義性:
static void M(S arg); static void M(in S arg);
如今,經過值(前面示例中的第一個)的重載比經過只讀引用版本的重載更好。 若要使用只讀引用參數調用版本,必須在調用方法前添加 in
修飾符。
有關詳細信息,請參閱有關 in
參數修飾符的文章。
out
變量聲明的語法進行了擴展,以包含字段初始值設定項、屬性初始值設定項、構造函數初始值設定項和查詢子句。 它容許使用如如下示例中所示的代碼:
public class B { public B(int i, out int j) { j = i; } } public class D : B { public D(int i) : base(i, out var j) { Console.WriteLine($"The value of 'j' is {j}"); } }
在每一個版本中,對重載解析規則進行了更新,以解決多義方法調用具備「明顯」選擇的狀況。此版本添加了三個新規則,以幫助編譯器選取明顯的選擇:
this
實例接收器沒法使用)包含未定義 this
的成員的正文(例如,靜態成員),以及不能使用 this
的位置(例如,字段初始值設定項和構造函數初始值設定項)。你將注意到此更改,由於當你肯定哪一個方法更好時,你將發現多義方法重載具備更少的編譯器錯誤。
-publicsign
編譯器選項指示編譯器使用公鑰對程序集進行簽名。 程序集被標記爲已簽名,但簽名取自公鑰。 此選項使你可以使用公鑰在開放源代碼項目中構建簽名的程序集。
有關詳細信息,請參閱 -publicsign 編譯器選項一文。
-pathmap
編譯器選項指示編譯器將生成環境中的源路徑替換爲映射的源路徑。 -pathmap
選項控制由編譯器編寫入 PDB 文件或爲 CallerFilePathAttribute 編寫的源路徑。
有關詳細信息,請參閱 -pathmap 編譯器選項一文。