.NET 帮助

C# 模式匹配表达式(开发者如何使用)

发布 2024年三月26日
分享:

介绍

C# 中的模式匹配是 C# 7.0 中引入的一项强大功能,并在随后的版本中不断扩展。 在处理条件语句、类型检查和对象解构时,它能让开发人员编写出更简洁、更具表现力的代码。

模式匹配表达式提供了一种灵活直观的方法,可将数值与模式匹配并执行相应的代码块。 在本文中,我们将探讨 C# 中模式匹配表达式的复杂性,包括语法、用例和代码示例。 在文章的最后,我们还将探讨以下内容IronPDF PDF 生成库铁软件在 C# 应用程序中即时生成 PDF 文档。

C# 中模式匹配的优点;

C# 代码中的模式匹配具有大量优势:

  • 增强可读性:模式匹配简化了复杂的条件逻辑,使您和其他开发人员更容易理解和遵循您的代码。
  • 减少代码行数:通过将复杂的条件语句浓缩为简洁的模式,模式匹配有助于精简代码库,从而减少代码行数,实现更简洁的实现。
  • 提高可维护性:模式匹配提供的清晰度使代码维护和调试更加容易。 有了清晰的模式划分,识别和修改所需的特定逻辑块就变得更加简单,而不会影响代码库的其他部分。
  • 更具表现力的算法:模式匹配使开发人员能够以更自然、更直观的方式表达算法。 通过将代码结构与解决问题的范例相统一,模式匹配有助于创建与其概念模型非常相似的算法。

C# 中的模式匹配类型 35;

以下表达式支持模式匹配:

  • 是表达
  • 开关语句
  • 开关表达式

    可使用以下模式与结构匹配:

声明和类型模式

声明和类型模式是 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#

在这里,声明模式确保如果表达式问候语与类型字符串匹配,就会将其分配给变量 message,从而实现后续操作。

如果以下任何条件成立,则声明模式有效:

  • 表达式的运行时类型为 T。
  • 表达式的运行时类型派生自 T、实现接口 T 或可隐式转换为 T。
  • 表达式的运行时类型是具有底层类型 T 的可空值类型。
  • 从表达式的运行时类型到类型 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 的可空值类型,而 "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#

在本片段中,_ 可作为任何匹配车辆类型的占位符。

声明模式和类型模式都能确保表达式在模式匹配前是非空的。 您可以使用否定空常量模式检查非空,如下图所示:

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

在进行进一步操作之前,该否定操作可确保输入不为空。

通过在 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. 声明的 const 字段或局部的名称。

  7. 无效。

    跨度类型表达式或 ReadOnlySpan可以匹配常量字符串。

    要检查空值,请使用常量模式,例如

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

在这里,该模式确保输入为空,然后再进行下一步操作。

您还可以使用否定空常量模式来确定非空值:

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

这种模式可以验证输入是否为空,从而保证后续操作的安全进行。

通过将常量模式纳入 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#

在这里,关系模式将测量结果与特定阈值进行比较,以确定其分类。

关系模式的右侧部分必须是常量表达式,可以是整数、浮点、字符或 "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#

本节选介绍了如何利用连词 "和 "模式,根据特定范围内的月份确定日历季节。 译文还提到,关系模式为比较表达式结果与常量提供了一种简洁而富有表现力的方法,从而提高了代码的清晰度和可维护性。

丢弃模式

丢弃模式(用 _ 表示)用于匹配任何表达式,包括空值。 以下面的例子为例:

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 _)来匹配任何表达式。 但是,在切换表达式中允许使用丢弃模式。 有关详细信息,请参阅功能提案说明中的 "丢弃模式 "部分。

逻辑模式

C# 中的逻辑模式为模式匹配提供了强大的工具,包括否定、连接和析取,可以实现更灵活、更具表现力的匹配条件。

否定(非模式)

否定模式(用 "not "表示)在否定模式不匹配表达式时匹配表达式。 如下所示,这对于检查表达式是否为非空特别有用:

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

在此,如果输入值不为空,则执行代码块。

连词(和模式)

连接模式使用 "和 "关键字,当两个模式都与表达式匹配时,该表达式就会匹配。 这样就可以将多个条件结合起来,如下例所示:

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 允许您匹配任何类型。 这对于捕捉布尔表达式中的中间结果或在 switch case guards 中需要进行多重检查时特别有用。

下面是一个在布尔表达式中使用 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 case guards 中使用 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 许可页面. 提供电子邮件 ID 以生成许可证密钥并发送至您的电子邮件。

"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# 中的模式匹配表达式为编写条件语句、类型检查和对象解构提供了强大而灵活的方式,简洁易读。 通过利用模式匹配,开发人员可以提高代码的清晰度和可维护性,同时减少模板和冗余。 无论是类型检查、开关语句还是解构,模式匹配表达式都为处理 C# 中的各种编程任务提供了多功能工具集。

总之,掌握模式匹配表达式可以大大提高您的 C# 编程技能,使您能够编写出更简洁、更具表现力、更易于理解和维护的代码。 我们还涉及IronPdf 的 HTML 至 PDF 生成能力此外,我们还将翻译可用于生成 PDF 文档的 .NET 和 .NET。

< 前一页
.NET 软件开发(如何为开发人员工作)
下一步 >
C# 内部实现(开发者如何使用)

准备开始了吗? 版本: 2024.12 刚刚发布

免费NuGet下载 总下载量: 11,781,565 查看许可证 >