C# 7.3 の新機能What's new in C# 7.3

C# 7.3 リリースには 2 つの主要なテーマがあります。There are two main themes to the C# 7.3 release. 1 つ目のテーマは、アンセーフ コードと同様のパフォーマンスをセーフ コードで確保するための機能の提供です。One theme provides features that enable safe code to be as performant as unsafe code. 2 つ目のテーマは、既存の機能のインクリメンタルな改善の提供です。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:

  • ピン留めを使用せずに fixed フィールドにアクセスできます。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:

  • タプル型を使用して ==!= をテストできます。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.

セーフ コードをより効率的にする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];
    }
}

変数 pmyFixedField の 1 個の要素にアクセスします。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# では、2 番目の固定ポインターを宣言する必要があります。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 T または ref readonly T を返す GetPinnableReference() メソッドを格納する型として fixed を使用できます。Starting with C# 7.3, any type that contains a GetPinnableReference() method that returns a ref T or ref readonly T may be fixed. この機能の追加により、fixedSystem.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.Enum 型または System.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. アンマネージ型は参照型ではない型であり、任意の入れ子のレベルに参照型を含みません。An unmanaged type is a type that isn't a reference type and doesn't contain any reference type at any level of nesting.

詳しくは、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

2 つ目のテーマは、言語の機能の改善の提供です。The second theme provides improvements to features in the language. 以下に示す機能によって、C# を記述する際の生産性が向上します。These features improve productivity when writing C#.

タプルによる ==!= のサポートTuples support == and !=

C# のタプル型で ==!= がサポートされるようになりました。The C# tuple types now support == and !=. 詳細については、タプルに関する記事の等値について説明したセクションを参照してください。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 メソッドのオーバーロードを解決するタイブレーカーin method overload resolution tiebreaker

in 引数修飾子が追加されると、次の 2 つのメソッドがあいまいさの原因となっていました。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);

現在では、値による (前述の例の最初の方法) オーバーロードが readonly 参照によるオーバーロードよりも優れています。Now, the by value (first in the preceding example) overload is better than the by readonly reference version. readonly 参照引数を使用してバージョンを呼び出すには、メソッドの呼び出し時に in 修飾子を含める必要があります。To call the version with the readonly reference argument, you must include the in modifier when calling the method.

注意

これはバグの修正として実装されました。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

out 変数の宣言を許可するために C# 7.0 に追加された構文が、フィールド初期化子、プロパティ初期化子、コンストラクター初期化子、およびクエリ句を含めるように拡張されました。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. このリリースでは、コンパイラが明らかな選択肢を選択できるようにする 3 つの新しいルールが追加されています。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.