定数文字列でのパターン マッチ
メモ
この記事は機能仕様についてです。 仕様は、機能の設計ドキュメントとして使用できます。 これには、提案された仕様の変更および機能の設計と開発時に必要な情報が含まれます。 これらの記事は、提案された仕様の変更が決定され、現在の ECMA 仕様に組み込まれるまで公開されます。
機能の仕様と行われた実装では、いくつかの違いがあることがあります。 これらの違いは、関連する言語設計ミーティング (LDM) メモに取り上げられています。
機能仕様を C# 言語標準に導入するプロセスの詳細については、仕様に関する記事を参照してください。
チャンピオンの課題: https://github.com/dotnet/csharplang/issues/8640
まとめ
Span<char>
型と ReadOnlySpan<char>
型の値を定数文字列に対してパターン マッチングできるようになります。
目的
パフォーマンスの観点から、多くのシナリオでは string 型よりも Span<char>
型と ReadOnlySpan<char>
型の使用が推奨されます。 このフレームワークでは、string
の代わりに ReadOnlySpan<char>
を使用できるように、多くの新しい API が追加されています。
文字列に対する一般的な操作は、特定の値であるかどうかを調べるために switch 文を使用することですが、コンパイラはこのような switch 文を最適化します。 しかし、ReadOnlySpan<char>
に対して同様のことを効率的に行う方法は、switch 文を実装して最適化を手動で行う以外には、現在のところありません。
ReadOnlySpan<char>
の導入を促進するために、ある ReadOnlySpan<char>
を一定の string
とパターンマッチングできるようにし、それによってスイッチでの使用も可能にします。
static bool Is123(ReadOnlySpan<char> s)
{
return s is "123";
}
static bool IsABC(Span<char> s)
{
return s switch { "ABC" => true, _ => false };
}
詳細な設計
定数パターンの仕様を次のように変更します (追加部分は太字で示しています)。
パターン入力値
e
および変換された値v
を持つ定数パターンP
が与えられた場合、
- e に整数型または列挙型、またはいずれかの null 許容形式があり、v に整数型がある場合、パターン
P
は、式e == v
の結果がtrue
の場合、値 e と一致します。それ以外の場合は次のようになります。- e が
System.Span<char>
型またはSystem.ReadOnlySpan<char>
型であり、c が定数文字列であり、c の定数値がnull
ではない場合、System.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(c))
がtrue
を返すと、パターンが一致したとみなされます。object.Equals(e, v)
がtrue
を返す場合、パターンP
は値 e と一致します。
既知のメンバー
System.Span<T>
と System.ReadOnlySpan<T>
は名前でマッチングされ、ref struct
である必要があり、corlib の外部で定義できます。
System.MemoryExtensions
は名前でマッチングされ、corlib の外部で定義できます。
System.MemoryExtensions.SequenceEqual
オーバーロードの署名が一致している必要があります。
public static bool SequenceEqual<T>(System.Span<T>, System.ReadOnlySpan<T>)
public static bool SequenceEqual<T>(System.ReadOnlySpan<T>, System.ReadOnlySpan<T>)
System.MemoryExtensions.AsSpan
のシグネチャは以下と一致する必要があります。
public static System.ReadOnlySpan<char> AsSpan(string)
パラメーターが省略可能なメソッドは対象外です。
デメリット
なし
代替
なし
未解決の質問
マッチングは
MemoryExtensions.SequenceEqual()
などから独立して定義する必要がありますか?...
e
のすべての文字について、e.Length == c.Length
およびe[i] == c[i]
が成り立つ場合、パターンは一致するとみなされます。推奨:
MemoryExtensions.SequenceEqual()
を指標にして性能を定義します。MemoryExtensions
が見つからない場合は、コンパイル エラーを報告します。(string)null
に対するマッチングは許可する必要がありますか?その場合、
(string)null
以降""
にMemoryExtensions.AsSpan(null) == MemoryExtensions.AsSpan("")
を含める必要がありますか?static bool IsEmpty(ReadOnlySpan<char> span) { return span switch { (string)null => true, // ok? "" => true, // error: unreachable? _ => false, }; }
推奨: 定数パターン
(string)null
はエラーとして報告する必要があります。定数パターン マッチングに
Span<char>
またはReadOnlySpan<char>
の式値の実行時型検査は必要ですか?static bool Is123<T>(Span<T> s) { return s is "123"; // test for Span<char>? } static bool IsABC<T>(Span<T> s) { return s is Span<char> and "ABC"; // ok? } static bool IsEmptyString<T>(T t) where T : ref struct { return t is ""; // test for ReadOnlySpan<char>, Span<char>, string? }
推奨: 定数パターンの実行時型検査は暗黙的に行われません。 (
IsABC<T>()
の例は、型検査が明示的であるため許可されます)この推奨は実装されませんでした。 前述のすべてのサンプルはコンパイル エラーとなります。
サブサンプションで、定数文字列パターン、リストパターン、および
Length
プロパティパターンを考慮すべきですか?static int ToNum(ReadOnlySpan<char> s) { return s switch { { Length: 0 } => 0, "" => 1, // error: unreachable? ['A',..] => 2, "ABC" => 3, // error: unreachable? _ => 4, }; }
推奨事項: 式の値が
string
の場合に使用されるのと同じサブサンプション動作。 これは、定数文字列、リストパターン、Length
の間での包含がなく、[..]
を何にでも一致するものとして扱うことを意味しますか?
デザイン会議
C# feature specifications