.NET ヘルプ

C# パターン マッチング式(開発者向けの仕組み)

公開済み 2024年3月26日
共有:

イントロダクション

C# のパターンマッチングは、C# 7.0 で導入され、その後のバージョンで拡張された強力な機能です。 開発者は条件文、型チェック、オブジェクトの分解に対処する際に、より簡潔で表現力豊かなコードを書くことができます。

パターンマッチング式は、値をパターンに対して照合し、対応するコードブロックを実行するための柔軟かつ直感的な方法を提供します。 この記事では、C#におけるパターンマッチングの表現の詳細について、構文、使用例、コードサンプルを含めて探ります。 記事の最後では、以下の点についても少し触れています。IronPDF PDF生成ライブラリからIron SoftwareC#アプリケーションでPDFドキュメントを瞬時に生成するために。

C#におけるパターンマッチングの利点#35;

C#コードにおけるパターンマッチングには、多くの利点があります:

  • 読みやすさの向上:パターンマッチングは複雑な条件ロジックを簡略化し、あなた自身や他の開発者にとってコードの理解と追従が容易になります。
  • コード行の削減: 複雑な条件文を簡潔なパターンにまとめることで、パターンマッチングはコードベースを合理化し、コード行数を減らし、より簡潔な実装につながります。
  • メンテナンス性の向上: パターンマッチングによって提供される明確さは、コードのメンテナンスとデバッグをより容易にします。 パターンが明確に示されると、必要に応じて特定のロジックブロックを他のコードベースに影響を与えずに識別して修正することが簡単になります。
  • より表現力のあるアルゴリズム:パターンマッチングにより、開発者はより自然で直感的な方法でアルゴリズムを表現することができます。 問題解決のパラダイムにコード構造を一致させることにより、パターンマッチングは概念モデルに非常に近いアルゴリズムの作成を容易にします。

C#35.パターンマッチの種類

パターンマッチングは、次の式によってサポートされています:

  • is expression (式)
  • スイッチステートメント
  • スイッチ式

    以下のパターンは、構文と一致させるために使用できます:

宣言と型パターン

宣言パターンと型パターンは、C#で式の実行時型が与えられた型と互換性があるかを確認するための重要なツールです。宣言パターンを使用すると、互換性の確認と新しいローカル変数の宣言を同時に行うことができます。 以下の例を考えてみてください:

object greeting = "Iron Software is Awesome!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: Iron Software is Awesome!
}
object greeting = "Iron Software is Awesome!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: Iron Software is Awesome!
}
Dim greeting As Object = "Iron Software is Awesome!"
Dim tempVar As Boolean = TypeOf greeting Is String
Dim message As String = If(tempVar, DirectCast(greeting, String), Nothing)
If tempVar Then
	Console.WriteLine(message.ToLower()) ' output: Iron Software is Awesome!
End If
VB   C#

宣言パターンは、式 greeting が型 string と一致する場合、その式が変数 message に代入され、その後の操作が可能になることを保証します。

以下の条件のいずれかが当てはまる場合、宣言パターンが有効です:

  • 式の実行時の型はTです。
  • 式の実行時型はTから派生し、インターフェースTを実装しているか、暗黙的にTに変換することができます。
  • 式の実行時の型は、基底型がTであるNullable値型です。
  • 式の実行時型から型Tへのボクシングまたはアンボクシング変換が存在します。

    次の例を考慮して、上記の条件を示します:

int? nullableX = 8;
int y = 45;
object boxedy = y;
if (nullableX is int a && boxedy is int b)
{
    Console.WriteLine(a + b);  // output: 53
}
int? nullableX = 8;
int y = 45;
object boxedy = y;
if (nullableX is int a && boxedy is int b)
{
    Console.WriteLine(a + b);  // output: 53
}
Dim nullableX? As Integer = 8
Dim y As Integer = 45
Dim boxedy As Object = y
Dim tempVar As Boolean = TypeOf boxedy Is Integer
Dim b As Integer = If(tempVar, DirectCast(boxedy, Integer), Nothing)
Dim tempVar2 As Boolean = TypeOf nullableX Is Integer
Dim a As Integer = If(tempVar2, CInt(nullableX), Nothing)
If tempVar2 AndAlso tempVar Then
	Console.WriteLine(a + b) ' output: 53
End If
VB   C#

ここで、nullableXは基本型がintのnull許容値型であるためパターンに一致し、boxedyはintにボックス化解除できるため一致します。

新しい変数を宣言せずに式の型を確認するだけでよい場合、以下の例に示されているように捨象 (_) を利用することができます。

public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
    bus _ => 4.00m,
    motor _ => 8.50m,
    null => throw new ArgumentNullException(nameof(vehicle)),
    _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
    bus _ => 4.00m,
    motor _ => 8.50m,
    null => throw new ArgumentNullException(nameof(vehicle)),
    _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
'{
'	bus _ => 4.00m,
'	motor _ => 8.50m,
'	null => throw new ArgumentNullException(nameof(vehicle)),
'	_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
'};
VB   C#

このスニペットでは、_ は Vehicle と一致する任意の型のプレースホルダーとして機能します。

宣言パターンと型パターンの両方が、パターンマッチングを行う前に式がnullでないことを保証します。 以下に示すように、否定されたnull定数パターンを使用して非nullをチェックすることができます:

if (inputVal is not null)
{
    // ...
}
if (inputVal is not null)
{
    // ...
}
If inputVal IsNot Nothing Then
	' ...
End If
VB   C#

これはネゲーションによって、後続の操作を続行する前に入力がnullでないことを確認します。

C#コードで宣言と型パターンを活用することにより、可読性を向上させ、コード行を削減し、アルゴリズムをより効果的に表現することができます。 これらのパターンは、型ベースのロジックを扱うための簡潔で表現力豊かな方法を提供し、コードベースの保守性を向上させます。

一定のパターン

定数パターンは、式の結果が特定の定数値と一致するかどうかを確認するために使用されます。 以下の例を考えてみてください:

public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
    1 => 2.0m,
    2 => 10.0m,
    3 => 25.0m,
    4 => 60.0m,
    0 => 0.0m,
    _ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};
public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
    1 => 2.0m,
    2 => 10.0m,
    3 => 25.0m,
    4 => 60.0m,
    0 => 0.0m,
    _ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};
Dim tempVar As Decimal
Select Case visitorCount
	Case 1
		tempVar = 2.0D
	Case 2
		tempVar = 10.0D
	Case 3
		tempVar = 25.0D
	Case 4
		tempVar = 60.0D
	Case 0
		tempVar = 0.0D
	Case Else
'INSTANT VB TODO TASK: Throw expressions are not converted by Instant VB:
'ORIGINAL LINE: tempVar = throw new ArgumentException(string.Format("Not supported number of visitors: {0}", visitorCount), nameof(visitorCount));
		tempVar = throw New ArgumentException($"Not supported number of visitors: {visitorCount}", NameOf(visitorCount))
End Select
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'public static decimal GetGroupTicketPrice(int visitorCount)
'{
'	Return tempVar;
'}
VB   C#

ここでは、定数パターンがvisitorCountが指定された定数値のいずれかに一致するかどうかを確認し、対応するチケット価格を返します。

常定パターンでは、次のようなさまざまな定数式を使用できます:

  1. 整数または浮動小数点数のリテラル。

  2. キャラクター.

  3. 文字列リテラル。

  4. ブール値(真か偽か).

  5. 列挙値。

  6. 宣言された定数フィールドまたはローカルの名前。

  7. ヌル。

    型Spanの式 または ReadOnlySpan 定数文字列に一致させることができます。

    nullチェックには、次のような定数パターンを使用します:

if (inputVal is null)
{
    return;
}
if (inputVal is null)
{
    return;
}
If inputVal Is Nothing Then
	Return
End If
VB   C#

ここで、パターンは入力がnullであることを確認してから、さらに処理を進めます。

また、ネゲートされた null 定数パターンを使用して非 null 値を確認することができます。

if (inputVal is not null)
{
    // ...
}
if (inputVal is not null)
{
    // ...
}
If inputVal IsNot Nothing Then
	' ...
End If
VB   C#

このパターンは、入力がnullでないことを確認し、その後の操作が安全に実行できるようにします。

C#コードに定数パターンを組み込むことにより、特定の定数値をマッチさせる必要があるシナリオを効果的に処理し、コードの明快さと保守性を向上させることができます。

リレーショナル・パターン

リレーショナルパターンは、式の結果を定数と比較する手段を提供します。 以下の例を考えてみてください:

Console.WriteLine(Classify(20));  // output: Too high
Console.WriteLine(Classify(double.NaN));  // output: Unknown
Console.WriteLine(Classify(4));  // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};
Console.WriteLine(Classify(20));  // output: Too high
Console.WriteLine(Classify(double.NaN));  // output: Unknown
Console.WriteLine(Classify(4));  // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};
Console.WriteLine(Classify(20)) ' output: Too high
Console.WriteLine(Classify(Double.NaN)) ' output: Unknown
Console.WriteLine(Classify(4)) ' output: Acceptable
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string Classify(double measurement) => measurement switch
'{
'	< -4.0 => "Too low",
'	> 10.0 => "Too high",
'	double.NaN => "Unknown",
'	_ => "Acceptable",
'};
VB   C#

ここでは、関係パターンは特定の閾値と測定値を比較してその分類を決定します。

関係パターンの右部分は、整数型、浮動小数点型、char型、またはenum型の定数式でなければなりません。 「<」、「>」、「<=」、または「>=」演算子を左側で使用できます。

特定の範囲内で式の結果を一致させるためには、以下に示すように連言およびパターンを使用します:

Console.WriteLine(GetCalendarSeason(new DateTime(2024, 3, 12)));  // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 7, 12)));  // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 2, 12)));  // output: winter
static string GetCalendarSeason(DateTime date) => date.Month switch
{
    >= 3 and < 6 => "spring",
    >= 6 and < 9 => "summer",
    >= 9 and < 12 => "autumn",
    12 or (>= 1 and < 3) => "winter",
    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 3, 12)));  // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 7, 12)));  // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2024, 2, 12)));  // output: winter
static string GetCalendarSeason(DateTime date) => date.Month switch
{
    >= 3 and < 6 => "spring",
    >= 6 and < 9 => "summer",
    >= 9 and < 12 => "autumn",
    12 or (>= 1 and < 3) => "winter",
    _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};
Console.WriteLine(GetCalendarSeason(New DateTime(2024, 3, 12))) ' output: spring
Console.WriteLine(GetCalendarSeason(New DateTime(2024, 7, 12))) ' output: summer
Console.WriteLine(GetCalendarSeason(New DateTime(2024, 2, 12))) ' output: winter
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string GetCalendarSeason(DateTime date) => date.Month switch
'{
'	>= 3 and < 6 => "spring",
'	>= 6 and < 9 => "summer",
'	>= 9 and < 12 => "autumn",
'	12 or (>= 1 and < 3) => "winter",
'	_ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
'};
VB   C#

以下は、「and」パターンを使用して、特定の範囲に月が含まれるかどうかに基づいてカレンダーの季節を判定する方法について説明しています。 また、リレーショナルパターンは、表現の結果を定数と比較するための簡潔で表現力豊かな手段を提供し、コードの明確さと保守性を向上させると述べられています。

廃棄パターン

破棄パターン(_で表される)は、null を含む任意の式に一致するために使用されます。 次の例を見てください:

Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));  // output: 5.0
Console.WriteLine(GetDiscountInPercent(null));  // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));  // output: 0.0
static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
    DayOfWeek.Monday => 0.5m,
    DayOfWeek.Tuesday => 12.5m,
    DayOfWeek.Wednesday => 7.5m,
    DayOfWeek.Thursday => 12.5m,
    DayOfWeek.Friday => 5.0m,
    DayOfWeek.Saturday => 2.5m,
    DayOfWeek.Sunday => 2.0m,
    _ => 0.0m,
};
Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));  // output: 5.0
Console.WriteLine(GetDiscountInPercent(null));  // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));  // output: 0.0
static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
    DayOfWeek.Monday => 0.5m,
    DayOfWeek.Tuesday => 12.5m,
    DayOfWeek.Wednesday => 7.5m,
    DayOfWeek.Thursday => 12.5m,
    DayOfWeek.Friday => 5.0m,
    DayOfWeek.Saturday => 2.5m,
    DayOfWeek.Sunday => 2.0m,
    _ => 0.0m,
};
Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday)) ' output: 5.0
Console.WriteLine(GetDiscountInPercent(Nothing)) ' output: 0.0
Console.WriteLine(GetDiscountInPercent(CType(10, DayOfWeek))) ' output: 0.0
Dim tempVar As Decimal
Select Case dayOfWeek
	Case DayOfWeek.Monday
		tempVar = 0.5D
	Case DayOfWeek.Tuesday
		tempVar = 12.5D
	Case DayOfWeek.Wednesday
		tempVar = 7.5D
	Case DayOfWeek.Thursday
		tempVar = 12.5D
	Case DayOfWeek.Friday
		tempVar = 5.0D
	Case DayOfWeek.Saturday
		tempVar = 2.5D
	Case DayOfWeek.Sunday
		tempVar = 2.0D
	Case Else
		tempVar = 0.0D
End Select
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'static decimal GetDiscountInPercent(System.Nullable(Of DayOfWeek) dayOfWeek)
'{
'	Return tempVar;
'}
VB   C#

上記の破棄パターンの例は、考えられるすべての入力値を処理しています。 週のすべての日が処理され、デフォルト値を表します。 これですべての可能な値が処理されます。 破棄パターンは、is 式や switch ステートメントでパターンとして利用できません。 このような場合、表現を一致させるために捨てるパターンとして var を用いることができます。例えば、var _ のように。 ただし、スイッチ式では破棄パターンが許可されています。 詳細については、機能提案ノートの「Discard パターン」セクションを参照してください。

論理パターン

C#の論理パターンは、否定、連言、選言などのパターンマッチングのための強力なツールを提供し、より柔軟で表現力豊かなマッチング条件を可能にします。

否定(not パターン)

否定パターン(‘not’ で表される)は、否定されたパターンが表現と一致しない場合にその表現と一致します。 これは、次に示すように、式が非nullであるかどうかを確認するのに非常に役立ちます。

if (input is not null)
{
    // ...
}
if (input is not null)
{
    // ...
}
If input IsNot Nothing Then
	' ...
End If
VB   C#

ここでは、入力が null でない場合にコードブロックが実行されます。

結合 (andパターン)

連言パターンでは、「and」キーワードを使用し、両方のパターンがその表現に一致した場合に、その表現と一致します。 次の例に示すように、複数の条件を組み合わせることができます:

Console.WriteLine(Classify(13));    // output: High
Console.WriteLine(Classify(-100));  // output: Too low
Console.WriteLine(Classify(5.7));   // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -40.0 => "Too low",
    >= -40.0 and < 0 => "Low",
    >= 0 and < 10.0 => "Acceptable",
    >= 10.0 and < 20.0 => "High",
    >= 20.0 => "Too high",
    double.NaN => "Unknown",
};
Console.WriteLine(Classify(13));    // output: High
Console.WriteLine(Classify(-100));  // output: Too low
Console.WriteLine(Classify(5.7));   // output: Acceptable
static string Classify(double measurement) => measurement switch
{
    < -40.0 => "Too low",
    >= -40.0 and < 0 => "Low",
    >= 0 and < 10.0 => "Acceptable",
    >= 10.0 and < 20.0 => "High",
    >= 20.0 => "Too high",
    double.NaN => "Unknown",
};
Console.WriteLine(Classify(13)) ' output: High
Console.WriteLine(Classify(-100)) ' output: Too low
Console.WriteLine(Classify(5.7)) ' output: Acceptable
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string Classify(double measurement) => measurement switch
'{
'	< -40.0 => "Too low",
'	>= -40.0 and < 0 => "Low",
'	>= 0 and < 10.0 => "Acceptable",
'	>= 10.0 and < 20.0 => "High",
'	>= 20.0 => "Too high",
'	double.NaN => "Unknown",
'};
VB   C#

この例では、測定値はその値の範囲に基づいて分類されます。

選択的(またはパターン)

分離パターンは、「or」キーワードを使用して、どちらのパターンでも一致する場合に表現と一致します。 これは以下のように複数の可能な条件を処理することができます:

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));  // output: winter
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));  // output: autumn
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));  // output: spring
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        3 or 4 or 5 => "spring",
        6 or 7 or 8 => "summer",
        9 or 10 or 11 => "autumn",
        12 or 1 or 2 => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));  // output: winter
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));  // output: autumn
    Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));  // output: spring
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        3 or 4 or 5 => "spring",
        6 or 7 or 8 => "summer",
        9 or 10 or 11 => "autumn",
        12 or 1 or 2 => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
Console.WriteLine(GetCalendarSeason(New DateTime(2021, 1, 19))) ' output: winter
	Console.WriteLine(GetCalendarSeason(New DateTime(2021, 10, 9))) ' output: autumn
	Console.WriteLine(GetCalendarSeason(New DateTime(2021, 5, 11))) ' output: spring
	Dim tempVar As String
	Select Case [date].Month
		Case 3, 4, 5
			tempVar = "spring"
		Case 6, 7, 8
			tempVar = "summer"
		Case 9, 10, 11
			tempVar = "autumn"
		Case 12, 1, 2
			tempVar = "winter"
		Case Else
'INSTANT VB TODO TASK: Throw expressions are not converted by Instant VB:
'ORIGINAL LINE: tempVar = throw new ArgumentOutOfRangeException(nameof(date), string.Format("Date with unexpected month: {0}.", date.Month));
			tempVar = throw New ArgumentOutOfRangeException(NameOf([date]), $"Date with unexpected month: {[date].Month}.")
	End Select
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'	static string GetCalendarSeason(DateTime @date)
'	{
'		Return tempVar;
'	}
VB   C#

ここでは、提供された日付の月に基づいてカレンダーの季節が決定されます。

これらのパターンコンビネータは、より複雑で正確なマッチング条件を作成するために繰り返し使用でき、コードの柔軟性と可読性を向上させます。

プロパティ・パターン

プロパティパターンは、式のプロパティやフィールドをネストされたパターンに対してマッチングすることを可能にします。 以下のコードスニペットでその例を見ることができます:

static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
Shared Function IsConferenceDay(ByVal [date] As DateTime) As Boolean
'INSTANT VB TODO TASK: The following 'is' operator pattern is not converted by Instant VB:
	Return [date] is { Year: 2020, Month: 5, Day: 19 [or] 20 [or] 21 }
End Function
VB   C#

ここでは、プロパティパターンが指定された日付が指定されたカンファレンスの日のいずれかに対応することを保証します。

以下のように、プロパティパターン内でランタイム型チェックと変数宣言を組み込むこともできます:

static string TakeFive(object input) => input switch
{
    string { Length: >= 5 } s => s.Substring(0, 5),
    string s => s,
    ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
    ICollection<char> symbols => new string(symbols.ToArray()),
    null => throw new ArgumentNullException(nameof(input)),
    _ => throw new ArgumentException("Unsupported input type."),
};
static string TakeFive(object input) => input switch
{
    string { Length: >= 5 } s => s.Substring(0, 5),
    string s => s,
    ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
    ICollection<char> symbols => new string(symbols.ToArray()),
    null => throw new ArgumentNullException(nameof(input)),
    _ => throw new ArgumentException("Unsupported input type."),
};
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string TakeFive(object input) => input switch
'{
'	string { Length: >= 5 } s => s.Substring(0, 5),
'	string s => s,
'	ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
'	ICollection<char> symbols => new string(symbols.ToArray()),
'	null => throw new ArgumentNullException(nameof(input)),
'	_ => throw new ArgumentException("Unsupported input type."),
'};
VB   C#

ここでは、プロパティパターンを使用して文字列および文字のコレクションを処理し、それらのプロパティに基づいて適切に処理されるようにします。

ポジショナルパターン

C#では、位置パターンは、式の結果を分解し、結果として得られる値を対応するネストされたパターンと照合することを可能にします。 例えば:

public readonly struct Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) => (X, Y) = (x, y);
    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
static string Classify(Point point) => point switch
{
    (0, 0) => "Origin",
    (1, 0) => "Positive X basis end",
    (0, 1) => "Positive Y basis end",
    _ => "Just a point",
};
public readonly struct Point
{
    public int X { get; }
    public int Y { get; }
    public Point(int x, int y) => (X, Y) = (x, y);
    public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
static string Classify(Point point) => point switch
{
    (0, 0) => "Origin",
    (1, 0) => "Positive X basis end",
    (0, 1) => "Positive Y basis end",
    _ => "Just a point",
};
'INSTANT VB WARNING: VB has no equivalent to the C# readonly struct:
'ORIGINAL LINE: public readonly struct Point
Public Structure Point
	Public ReadOnly Property X() As Integer
	Public ReadOnly Property Y() As Integer
	Public Sub New(ByVal x As Integer, ByVal y As Integer)
'INSTANT VB TODO TASK: VB has no equivalent to the C# deconstruction assignments:
		(X, Y) = (x, y)
	End Sub
	Public Sub Deconstruct(<System.Runtime.InteropServices.Out()> ByRef x As Integer, <System.Runtime.InteropServices.Out()> ByRef y As Integer)
'INSTANT VB TODO TASK: VB has no equivalent to the C# deconstruction assignments:
		(x, y) = (X, Y)
	End Sub
End Structure
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static string Classify(Point point) => point switch
'{
'	(0, 0) => "Origin",
'	(1, 0) => "Positive X basis end",
'	(0, 1) => "Positive Y basis end",
'	_ => "Just a point",
'};
VB   C#

この例では、位置パターンを利用して座標に基づいてポイントを分類します。

さらに、C# 10で導入された拡張プロパティパターンとして、プロパティパターン内のネストされたプロパティやフィールドを参照することができます。

static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start.Y: 0 } or { End.Y: 0 };
static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start.Y: 0 } or { End.Y: 0 };
Shared Function IsAnyEndOnXAxis(ByVal segment As Segment) As Boolean
'INSTANT VB TODO TASK: The following 'is' operator pattern is not converted by Instant VB:
	Return segment is { Start.Y: 0 } [or] { [End].Y: 0 }
End Function
VB   C#

この機能により、入れ子になったプロパティに直接アクセスできるようになり、プロパティパターンの柔軟性が向上します。

これらのパターンは、複雑なデータ構造の処理やコードの可読性および表現力の向上に強力なメカニズムを提供します。

パターン

Var Patternは、あらゆるタイプにマッチします。 これは、ブール式内の中間結果をキャプチャする場合や、複数のチェックがスイッチケースガードで必要な場合に特に役立ちます。

以下は、ブール式で var パターンの使用を示す例です:

static bool IsAcceptable(int id, int absLimit) =>
    SimulateDataFetch(id) is var results 
    && results.Min() >= -absLimit 
    && results.Max() <= absLimit;
static int [] SimulateDataFetch(int id)
{
    var rand = new Random();
    return Enumerable
               .Range(start: 0, count: 5)
               .Select(s => rand.Next(minValue: -10, maxValue: 11))
               .ToArray();
}
static bool IsAcceptable(int id, int absLimit) =>
    SimulateDataFetch(id) is var results 
    && results.Min() >= -absLimit 
    && results.Max() <= absLimit;
static int [] SimulateDataFetch(int id)
{
    var rand = new Random();
    return Enumerable
               .Range(start: 0, count: 5)
               .Select(s => rand.Next(minValue: -10, maxValue: 11))
               .ToArray();
}
Shared Function IsAcceptable(ByVal id As Integer, ByVal absLimit As Integer) As Boolean
	Dim tempVar As Boolean = TypeOf SimulateDataFetch(id) Is var
	Dim results = If(tempVar, CType(SimulateDataFetch(id), var), Nothing)
	Return tempVar AndAlso results.Min() >= -absLimit AndAlso results.Max() <= absLimit
End Function
Shared Function SimulateDataFetch(ByVal id As Integer) As Integer()
	Dim rand = New Random()
	Return Enumerable.Range(start:= 0, count:= 5).Select(Function(s) rand.Next(minValue:= -10, maxValue:= 11)).ToArray()
End Function
VB   C#

この例では、SimulateDataFetch は整数の配列を返し、is var パターンが結果を results 変数にキャプチャし、その特性に基づいて後続の計算を行うことができます。

さらに、var パターンは switch 式やステートメント内で使用でき、より簡潔で読みやすいコードを書くことができます。 次の例は、switch case ガードで var パターンを使用する例です:

public record Point(int X, int Y);
static Point Transform(Point point) => point switch
{
    var (x, y) when x < y => new Point(-x, y),
    var (x, y) when x > y => new Point(x, -y),
    var (x, y) => new Point(x, y),
};
static void TestTransform()
{
    Console.WriteLine(Transform(new Point(1, 2)));  // output: Point { X = -1, Y = 2 }
    Console.WriteLine(Transform(new Point(5, 2)));  // output: Point { X = 5, Y = -2 }
}
public record Point(int X, int Y);
static Point Transform(Point point) => point switch
{
    var (x, y) when x < y => new Point(-x, y),
    var (x, y) when x > y => new Point(x, -y),
    var (x, y) => new Point(x, y),
};
static void TestTransform()
{
    Console.WriteLine(Transform(new Point(1, 2)));  // output: Point { X = -1, Y = 2 }
    Console.WriteLine(Transform(new Point(5, 2)));  // output: Point { X = 5, Y = -2 }
}
'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Point(int X, int Y)
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'static Point Transform(Point point) => point switch
'{
'	var (x, y) when x < y => new Point(-x, y),
'	var (x, y) when x > y => new Point(x, -y),
'	var (x, y) => new Point(x, y),
'};
Shared Sub TestTransform()
	Console.WriteLine(Transform(New Point(1, 2))) ' output: Point { X = -1, Y = 2 }
	Console.WriteLine(Transform(New Point(5, 2))) ' output: Point { X = 5, Y = -2 }
End Sub
VB   C#

この例では、var パターン(x、y)点の座標をキャプチャし、値に基づいてさまざまな変換を可能にします。

「var パターンでは、宣言された変数の型は、パターンに対してマッチングされている式のコンパイル時の型から推論されます。」

var パターンは、特定の式の型が事前にわからないさまざまなシナリオを処理する便利な方法を提供し、コードの明確性と柔軟性を向上させます。

IronPDFライブラリの紹介

IronPDF ドキュメントレンダリングは、Iron SoftwareによるPDFドキュメント生成を専門とするライブラリです。 始めるには、まずNuGetパッケージマネージャーまたはVisual Studioパッケージマネージャーからライブラリをインストールします。

Install-Package IronPdf

以下の画像は、からのインストール方法を示していますVisual Studioインストールガイド.

C# パターンマッチング式 (開発者向けの使い方): 図1 - NuGet パッケージマネージャーで IronPDF をインストールする

以下のコードでは、シンプルなPDFドキュメントを生成する方法を見ていきます:

namespace IronPatterns;
class Program
{
    static void Main()
    {
        Console.WriteLine("-----------Iron Software-------------");
        var renderer = new ChromePdfRenderer(); // var pattern
        var content = " <h1> Iron Software is Awesome </h1> Made with IronPDF!";
        // Declaration Pattern
        int? nullableX = 8;
        int y = 45;
        object boxedy = y;
        content += "<p>Declaration Pattern</p>";
        if (nullableX is int a && boxedy is int b)
        {
            Console.WriteLine(a + b); // output: 53
            content += $"<p>Ouput:{(a + b)}</p>";
        }
        //Relational patterns
        content += "<p>Relational patterns</p>";
        var season1 = GetCalendarSeason(new DateTime(2024, 2, 25));
        Console.WriteLine(season1);
        content += $"<p>2024, 2, 25:{season1}</p>";
        var season2 = GetCalendarSeason(new DateTime(2024, 5, 25));
        Console.WriteLine(season2);
        content += $"<p>2024, 5, 25:{season1}</p>";
        var season3 = GetCalendarSeason(new DateTime(2024, 7, 25));
        Console.WriteLine(season3);
        content += $"<p>2024, 7, 25:{season1}</p>";
        var pdf = renderer.RenderHtmlAsPdf(content);
        pdf.SaveAs("output.pdf"); // Saves our PdfDocument object as a PDF        
    }
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        >= 3 and < 6 => "spring",
        >= 6 and < 9 => "summer",
        >= 9 and < 12 => "autumn",
        12 or (>= 1 and < 3) => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
}
namespace IronPatterns;
class Program
{
    static void Main()
    {
        Console.WriteLine("-----------Iron Software-------------");
        var renderer = new ChromePdfRenderer(); // var pattern
        var content = " <h1> Iron Software is Awesome </h1> Made with IronPDF!";
        // Declaration Pattern
        int? nullableX = 8;
        int y = 45;
        object boxedy = y;
        content += "<p>Declaration Pattern</p>";
        if (nullableX is int a && boxedy is int b)
        {
            Console.WriteLine(a + b); // output: 53
            content += $"<p>Ouput:{(a + b)}</p>";
        }
        //Relational patterns
        content += "<p>Relational patterns</p>";
        var season1 = GetCalendarSeason(new DateTime(2024, 2, 25));
        Console.WriteLine(season1);
        content += $"<p>2024, 2, 25:{season1}</p>";
        var season2 = GetCalendarSeason(new DateTime(2024, 5, 25));
        Console.WriteLine(season2);
        content += $"<p>2024, 5, 25:{season1}</p>";
        var season3 = GetCalendarSeason(new DateTime(2024, 7, 25));
        Console.WriteLine(season3);
        content += $"<p>2024, 7, 25:{season1}</p>";
        var pdf = renderer.RenderHtmlAsPdf(content);
        pdf.SaveAs("output.pdf"); // Saves our PdfDocument object as a PDF        
    }
    static string GetCalendarSeason(DateTime date) => date.Month switch
    {
        >= 3 and < 6 => "spring",
        >= 6 and < 9 => "summer",
        >= 9 and < 12 => "autumn",
        12 or (>= 1 and < 3) => "winter",
        _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
    };
}
Namespace IronPatterns
	Friend Class Program
		Shared Sub Main()
			Console.WriteLine("-----------Iron Software-------------")
			Dim renderer = New ChromePdfRenderer() ' var pattern
			Dim content = " <h1> Iron Software is Awesome </h1> Made with IronPDF!"
			' Declaration Pattern
			Dim nullableX? As Integer = 8
			Dim y As Integer = 45
			Dim boxedy As Object = y
			content &= "<p>Declaration Pattern</p>"
			Dim tempVar As Boolean = TypeOf boxedy Is Integer
			Dim b As Integer = If(tempVar, DirectCast(boxedy, Integer), Nothing)
			Dim tempVar2 As Boolean = TypeOf nullableX Is Integer
			Dim a As Integer = If(tempVar2, CInt(nullableX), Nothing)
			If tempVar2 AndAlso tempVar Then
				Console.WriteLine(a + b) ' output: 53
				content &= $"<p>Ouput:{(a + b)}</p>"
			End If
			'Relational patterns
			content &= "<p>Relational patterns</p>"
			Dim season1 = GetCalendarSeason(New DateTime(2024, 2, 25))
			Console.WriteLine(season1)
			content &= $"<p>2024, 2, 25:{season1}</p>"
			Dim season2 = GetCalendarSeason(New DateTime(2024, 5, 25))
			Console.WriteLine(season2)
			content &= $"<p>2024, 5, 25:{season1}</p>"
			Dim season3 = GetCalendarSeason(New DateTime(2024, 7, 25))
			Console.WriteLine(season3)
			content &= $"<p>2024, 7, 25:{season1}</p>"
			Dim pdf = renderer.RenderHtmlAsPdf(content)
			pdf.SaveAs("output.pdf") ' Saves our PdfDocument object as a PDF
		End Sub
'INSTANT VB TODO TASK: The following 'switch expression' was not converted by Instant VB:
'		static string GetCalendarSeason(DateTime date) => date.Month switch
'		{
'			>= 3 and < 6 => "spring",
'			>= 6 and < 9 => "summer",
'			>= 9 and < 12 => "autumn",
'			12 or (>= 1 and < 3) => "winter",
'			_ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
'		};
	End Class
End Namespace
VB   C#

出力

C# パターンマッチング式 (開発者向けの動作方法): 図 2

コード詳細

ここでは、IronPDFのChromePdfRendererクラス HTML文字列をPDF文書に保存します。 出力は「output.pdf」ドキュメントに保存されます。

トライアルライセンス

IronPdfは、以下のツールで使用できます。試用ライセンス以下より入手IronPDF ライセンスページ. ライセンスキーをメールに配信するために、メールアドレスを提供してください。

"IronPDF.LicenseKey": "<Your Key>"
"IronPDF.LicenseKey": "<Your Key>"
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'"IronPDF.LicenseKey": "<Your Key>"
VB   C#

上記のように、ライセンスキーをAppSettings.Jsonファイルに配置してください。

結論

C# におけるパターンマッチング式は、条件文、型チェック、およびオブジェクトの分解を簡潔かつ読みやすい方法で記述するための強力で柔軟な手段を提供します。 パターンマッチングを活用することで、開発者はボイラープレートコードや冗長性を減らしながら、コードの明確性と保守性を向上させることができます。 型チェック、switchステートメント、または分解のいずれであっても、パターンマッチング式はC#の幅広いプログラミングタスクに対処するための多用途なツールセットを提供します。

結論として、パターンマッチング式を習得することは、C#プログラミングのスキルを大幅に向上させることができ、よりクリーンで理解しやすく、保守しやすいコードを書くことを可能にします。 またIronPDFのHTMLからPDFへの生成機能また、PDFドキュメントを生成するために活用できる、.NET、Java、Python、またはNode.jsを使用しています。

< 以前
.NETソフトウェア開発(開発者向けの仕組み)
次へ >
C# 内部 (開発者向けの仕組み)