C# 7.3 的新功能What's new in C# 7.3

C# 7.3 版有兩個主要的佈景主題。There are two main themes to the C# 7.3 release. 其中一個佈景主題提供了使安全的程式碼具有與不安全的程式碼一樣高效能的功能。One theme provides features that enable safe code to be as performant as unsafe code. 第二個佈景主題提供現有功能的累加增強功能。The second theme provides incremental improvements to existing features. 此外,此版本中加入了新的編譯器選項。In addition, new compiler options were added in this release.

下列新功能針對安全的程式碼支援較佳效能的佈景主題:The following new features support the theme of better performance for safe code:

  • 您可以在不釘選的情況下存取固定的欄位。You can access fixed fields without pinning.
  • 您可以重新指派 ref 區域變數。You can reassign ref local variables.
  • 您可以在 stackalloc 陣列上使用初始設定式。You can use initializers on stackalloc arrays.
  • 您可以搭配支援模式的任何型別使用 fixed 陳述式。You can use fixed statements with any type that supports a pattern.
  • 您可以使用其他的泛型限制式。You can use additional generic constraints.

已在現有功能中提供下列增強功能:The following enhancements were made to existing features:

  • 您可以使用 Tuple 型別測試 ==!=You can test == and != with tuple types.
  • 您可以在更多位置使用運算式變數。You can use expression variables in more locations.
  • 您可以將屬性附加至自動實作屬性的支援欄位。You may attach attributes to the backing field of auto-implemented properties.
  • 已改善當引數依 in 不同時的方法解析。Method resolution when arguments differ by in has been improved.
  • 多載解析現在會有較少模稜兩可的情況。Overload resolution now has fewer ambiguous cases.

新的編譯器選項:The new compiler options are:

  • -publicsign,用來啟用組件的開放原始碼軟體 (OSS) 簽署。-publicsign to enable Open Source Software (OSS) signing of assemblies.
  • -pathmap,用來提供來源目錄的對應。-pathmap to provide a mapping for source directories.

這篇文章的其餘部分提供詳細資料和連結,讓您深入了解每個增強功能。The remainder of this article provides details and links to learn more about each of the improvements. 您可以使用 dotnet try 全域工具,在您的環境中探索這些功能:You can explore these features in your environment using the dotnet try global tool:

  1. 安裝 dotnet-try 全域工具。Install the dotnet-try global tool.
  2. 複製 dotnet/try-samples 存放庫。Clone the dotnet/try-samples repository.
  3. 將目前目錄設為 try-samples 存放庫的 csharp7 子目錄。Set the current directory to the csharp7 subdirectory for the try-samples repository.
  4. 執行 dotnet tryRun dotnet try.

啟用更有效率的安全的程式碼Enabling more efficient safe code

您應該能夠安全地撰寫與不安全的程式碼一樣高效能的 C# 程式碼。You should be able to write C# code safely that performs as well as unsafe code. 安全的程式碼可避免一些錯誤類別,例如緩衝區溢位、偏離的指標和其他記憶體存取錯誤。Safe code avoids classes of errors, such as buffer overruns, stray pointers, and other memory access errors. 這些新功能擴充了可驗證安全的程式碼的功能。These new features expand the capabilities of verifiable safe code. 儘可能使用安全的建構來撰寫更多的程式碼。Strive to write more of your code using safe constructs. 這些功能都讓這變得更容易。These features make that easier.

索引 fixed 欄位不需要釘選Indexing fixed fields does not require pinning

請考量此建構:Consider this struct:

unsafe struct S
{
    public fixed int myFixedField[10];
}

在舊版的 C# 中,您需要釘選變數,才能存取屬於 myFixedField 的其中一個整數。In earlier versions of C#, you needed to pin a variable to access one of the integers that are part of myFixedField. 現在,下列程式碼會進行編譯而不將變數 p 固定在個別的 fixed 陳述式內:Now, the following code compiles without pinning the variable p inside a separate fixed statement:

class C
{
    static S s = new S();

    unsafe public void M()
    {
        int p = s.myFixedField[5];
    }
}

變數 p 會存取 myFixedField 中的一個元素。The variable p accesses one element in myFixedField. 您不需要宣告個別的 int* 變數。You don't need to declare a separate int* variable. 請注意,您仍然需要 unsafe 內容。Note that you still need an unsafe context. 在舊版的 C# 中,您需要宣告第二個固定指標:In earlier versions of C#, you need to declare a second fixed pointer:

class C
{
    static S s = new S();

    unsafe public void M()
    {
        fixed (int* ptr = s.myFixedField)
        {
            int p = ptr[5];
        }
    }
}

如需詳細資訊,請參閱有關 fixed 陳述式的文章。For more information, see the article on the fixed statement.

ref 區域變數可能會重新指派ref local variables may be reassigned

現在,ref 區域變數可能會在初始化之後被重新指派,以參照不同的執行個體。Now, ref locals may be reassigned to refer to different instances after being initialized. 下列程式碼現在會編譯:The following code now compiles:

ref VeryLargeStruct refLocal = ref veryLargeStruct; // initialization
refLocal = ref anotherVeryLargeStruct; // reassigned, refLocal refers to different storage.

如需詳細資訊,請參閱有關 ref 傳回和 ref 區域變數的文章,以及有關 foreach 的文章。For more information, see the article on ref returns and ref locals, and the article on foreach.

stackalloc 陣列支援初始設定式stackalloc arrays support initializers

您可以在初始化陣列時,指定陣列中元素的值:You've been able to specify the values for elements in an array when you initialize it:

var arr = new int[3] {1, 2, 3};
var arr2 = new int[] {1, 2, 3};

現在,相同的語法可以套用至使用 stackalloc 宣告的陣列:Now, that same syntax can be applied to arrays that are declared with stackalloc:

int* pArr = stackalloc int[3] {1, 2, 3};
int* pArr2 = stackalloc int[] {1, 2, 3};
Span<int> arr = stackalloc [] {1, 2, 3};

如需詳細資訊,請參閱 stackalloc 運算子一文。For more information, see the stackalloc operator article.

更多型別支援 fixed 陳述式More types support the fixed statement

fixed 陳述式支援一組有限的型別。The fixed statement supported a limited set of types. 從 C# 7.3 開始,包含傳回 ref Tref readonly TGetPinnableReference() 方法的任何型別都可能是 fixedStarting with C# 7.3, any type that contains a GetPinnableReference() method that returns a ref T or ref readonly T may be fixed. 新增此功能表示 fixed 可以與 System.Span<T> 和相關型別一起使用。Adding this feature means that fixed can be used with System.Span<T> and related types.

如需詳細資訊,請參閱語言參考中的 fixed 陳述式一文。For more information, see the fixed statement article in the language reference.

增強泛型限制式Enhanced generic constraints

您現在可以指定型別 System.EnumSystem.Delegate 作為型別參數的基底類別限制式。You can now specify the type System.Enum or System.Delegate as base class constraints for a type parameter.

您也可以使用新的 unmanaged 限制式指定型別參數必須是非受控型別You can also use the new unmanaged constraint, to specify that a type parameter must be an unmanaged type.

如需詳細資訊,請參閱有關 where 泛型限制式型別參數的限制式的文章。For more information, see the articles on where generic constraints and constraints on type parameters.

將這些條件約束新增至現有型別是不相容變更Adding these constraints to existing types is an incompatible change. 封閉式泛型型別可能不再符合這些新的條件約束。Closed generic types may no longer meet these new constraints.

讓現有的功能變得更好Make existing features better

第二個佈景主題提供了語言功能的改進。The second theme provides improvements to features in the language. 撰寫 C# 時,這些功能可以提高生產力。These features improve productivity when writing C#.

Tuple 支援 ==!=Tuples support == and !=

C# Tuple 型別現在支援 ==!=The C# tuple types now support == and !=. 如需詳細資訊,請參閱 Tuple 文章中涵蓋相等的一節。For more information, see the section covering equality in the article on tuples.

將屬性附加至自動實作屬性的支援欄位Attach attributes to the backing fields for auto-implemented properties

現在支援此語法:This syntax is now supported:

[field: SomeThingAboutFieldAttribute]
public int SomeProperty { get; set; }

屬性 SomeThingAboutFieldAttribute 套用至編譯器針對 SomeProperty 產生的支援欄位。The attribute SomeThingAboutFieldAttribute is applied to the compiler generated backing field for SomeProperty. 如需詳細資訊,請參閱 C# 程式設計指南中的屬性For more information, see attributes in the C# programming guide.

in 方法多載解析 tiebreakerin method overload resolution tiebreaker

當加入 in 引數修飾詞時,這兩種方法會造成模稜兩可:When the in argument modifier was added, these two methods would cause an ambiguity:

static void M(S arg);
static void M(in S arg);

現在,by 值 (上述範例中的第一個) 多載會優於 by 唯讀參考版本。Now, the by value (first in the preceding example) overload is better than the by readonly reference version. 若要呼叫具有唯讀參考引數的版本,您呼叫方法時必須包含 in 修飾詞。To call the version with the readonly reference argument, you must include the in modifier when calling the method.

注意

這已實作為錯誤 (Bug) 修正。This was implemented as a bug fix. 即使將語言版本設定為 "7.2",這也不再模棱兩可。This no longer is ambiguous even with the language version set to "7.2".

如需詳細資訊,請參閱有關 in 參數修飾詞的文章。For more information, see the article on the in parameter modifier.

在初始設定式中擴充運算式變數Extend expression variables in initializers

加入 C# 7.0 中以允許 out 變數宣告的語法已經擴充,以包含欄位初始設定式、屬性初始設定式、建構函式初始設定式和查詢子句。The syntax added in C# 7.0 to allow out variable declarations has been extended to include field initializers, property initializers, constructor initializers, and query clauses. 它讓您能執行如下列範例的程式碼:It enables code such as the following example:

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}");
   }
}

改進的多載候選項目Improved overload candidates

在每個版本中,多載解析規則都會更新,以解決模稜兩可的方法引動過程具有「明確」選項的情況。In every release, the overload resolution rules get updated to address situations where ambiguous method invocations have an "obvious" choice. 此版本新增三個新的規則,以協助編譯器挑選明確的選項:This release adds three new rules to help the compiler pick the obvious choice:

  1. 當方法群組同時包含執行個體和靜態成員時,如果在沒有執行個體接收者或內容的情況下叫用方法,編譯器會捨棄執行個體成員。When a method group contains both instance and static members, the compiler discards the instance members if the method was invoked without an instance receiver or context. 如果使用執行個體接收者叫用方法,編譯器就會捨棄靜態成員。The compiler discards the static members if the method was invoked with an instance receiver. 沒有接收者時,編譯器只會在靜態內容中包含靜態成員,否則將同時包含靜態成員和執行個體成員。When there is no receiver, the compiler includes only static members in a static context, otherwise both static and instance members. 當無法確定接收者是執行個體或型別時,編譯器會包含兩者。When the receiver is ambiguously an instance or type, the compiler includes both. 無法使用隱含 this 執行個體接收者的靜態內容,包括未定義 this 的成員主體 (例如靜態成員),以及不能使用 this 的位置 (例如欄位初始設定式和建構函式初始設定式)。A static context, where an implicit this instance receiver cannot be used, includes the body of members where no this is defined, such as static members, as well as places where this cannot be used, such as field initializers and constructor-initializers.
  2. 當方法群組包含某些型別引數不滿足其限制式的泛型方法時,這些成員將會從候選集合中移除。When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.
  3. 針對方法群組轉換,其傳回型別與委派的傳回型別不符合的候選方法,將會從集合中移除。For a method group conversion, candidate methods whose return type doesn't match up with the delegate's return type are removed from the set.

您只會注意到此變更,因為若確定何種方法較佳,就會發現模稜兩可的方法多載會有較少的編譯器錯誤。You'll only notice this change because you'll find fewer compiler errors for ambiguous method overloads when you are sure which method is better.

新的編譯器選項New compiler options

新的編譯器選項支援 C# 程式的新組建和 DevOps 案例。New compiler options support new build and DevOps scenarios for C# programs.

公用或開放原始碼簽署Public or Open Source signing

-publicsign 編譯器選項會指示編譯器使用公開金鑰簽署組件。The -publicsign compiler option instructs the compiler to sign the assembly using a public key. 該組件標示為已簽署,但簽章取自公開金鑰。The assembly is marked as signed, but the signature is taken from the public key. 此選項可讓您使用公開金鑰,從開放原始碼專案建置簽署的組件。This option enables you to build signed assemblies from open-source projects using a public key.

如需詳細資訊,請參閱 -publicsign 編譯器選項一文。For more information, see the -publicsign compiler option article.

pathmappathmap

-pathmap 編譯器選項會指示編譯器使用對應的來源路徑取代建置環境的來源路徑。The -pathmap compiler option instructs the compiler to replace source paths from the build environment with mapped source paths. -pathmap 選項控制編譯器寫入 PDB 檔案或 CallerFilePathAttribute 的來源路徑。The -pathmap option controls the source path written by the compiler to PDB files or for the CallerFilePathAttribute.

如需詳細資訊,請參閱 -pathmap 編譯器選項一文。For more information, see the -pathmap compiler option article.