IRONSOFTWAREHOME
開發者更新

C# 模式比對表達式(對於開發者的運行原理)

Jacob Mellor,首席技術官 @ Team Iron
Jacob Mellor
Updated: 2026年4月21日

C#中的模式匹配是一項強大的功能,首次在C# 7.0中引入,之後在隨後的版本中進一步擴展。 它允許開發者在處理條件語句、型別檢查和物件解構時,撰寫更為簡潔和富於表現力的程式碼。

模式匹配表達式提供了一種靈活和直觀的方法,以比對值與模式並執行相應的程式碼塊。 在本文中,我們將探討C#中模式匹配表達式的複雜性,包含語法、使用案例和程式碼範例。 本文結尾,我們還將稍微探討來自Iron Software的IronPDF PDF生成庫,以便在C#應用程式中動態生成PDF文件。

Benefits of Pattern Matching in C#

C#程式碼中的模式匹配具有許多優勢:

  • **提高可讀性:**模式匹配簡化了複雜的條件邏輯,使您的程式碼對於您自己和其他開發者來說更容易理解和跟隨。
  • **減少程式碼行數:**通過將複雜的條件語句凝練為簡潔的模式,模式匹配有助於簡化您的程式碼庫,導致更少的程式碼行數和更簡練的實現。
  • **改善可維護性:**模式匹配帶來的明確性促進了更容易的程式碼維護和除錯。 由於模式清晰分明,因此更容易識別和修改特定邏輯塊,而不影響其餘程式碼庫。
  • **更具表現力的算法:**模式匹配使開發者能夠以更自然和直觀的方式表達算法。 通過將程式碼結構與問題解決範型一致,模式匹配促進了建立與概念模型密切相似的算法。

Types of Pattern Matching in C#

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

  • is 表達式
  • switch 語句
  • switch 表達式

以下模式可用於與構造匹配:

聲明和型別模式

聲明和型別模式是在C#中檢查表達式運行時型別與給定型別相容性的基本工具。 通過聲明模式,您可以同時檢查相容性並聲明新的局部變數。 請考慮以下範例:

object greeting = "Iron Software is Awesome!";
if (greeting is string message)
{
    Console.WriteLine(message.ToLower());  // output: iron software is awesome!
}

在此,聲明模式確保如果表達式message,從而啟用後續操作。

當以下任何一種情況成立時,聲明模式就有效:

  • 表達式的運行時型別是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。

當您只需要檢查表達式的型別而不需要聲明新的變數時,您可以使用丟棄_,如下例所示:

public static decimal CalculateToll(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)),
};

在這段程式碼片段中,Vehicle匹配的型別的佔位符。

聲明和型別模式都確保表達式在模式匹配之前是非空的。 您可以使用否定的空常量模式檢查非空,如下所示:

if (inputVal is not null)
{
    // ...
}

此否定確保inputVal在進行進一步操作之前不是空值。

通過在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)),
};

在此,常量模式檢查visitorCount是否符合指定的任何常量值並返回相應的票價。

在常量模式中,您可以使用各種型別的常量表達式,例如:

  1. 整數或浮點數字面量。
  2. 字元。
  3. 字串字面量。
  4. 布林值(false)。
  5. 枚舉值。
  6. 聲明的常量字段或局部的名稱。
  7. null.

型別ReadOnlySpan<char>的表達式可以匹配常量字串。

要檢查null,請使用如下的常量模式:

if (inputVal is null)
{
    return;
}

在此,模式確保inputVal在進行進一步操作之前是空值。

您還可以使用否定的空常量模式來確認非空值:

if (inputVal is not null)
{
    // ...
}

此模式驗證inputVal不是空的,允許安全地執行後續操作。

通過在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",
};

在此,關係模式將measurement與特定的閾值進行比較以確定其分類。

關係模式的右側必須是常量表達式,可能是整數、浮點數、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}."),
};

此摘錄描述了如何利用連接的"和"模式根據月份落在特定範圍內來確定日曆季節。 它還提到關係模式提供了一種簡潔而富有表現力的方式來將表達式結果與常量進行比較,從而提高程式碼的清晰度和可維護性。

丟棄模式

丟棄模式由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,
};

在上述丟棄模式範例中,它處理所有可能的輸入值。 一周中的所有天數都得到管理,並提供了預設值。 借此,處理了所有可能的值。 丟棄模式不能作為switch語句中的模式使用。 在此類情況下,可以將var _,以匹配任何表達式。 然而,在switch表達式中允許使用丟棄模式。 欲了解更多詳情,請參閱功能提案說明中的丟棄模式部分。

邏輯模式

C#中的邏輯模式提供了強大的模式匹配工具,包括否定、連接和分離,這使得匹配條件更加靈活和富有表現力。

否定 (not模式)

否定模式由not表示,當否定模式不匹配表達式時匹配一個表達式。 這對於檢查表達式是否為非空特別有用,如下所示:

if (input is not null)
{
    // ...
}

在此,如果input不是空值,則執行程式碼塊。

連接 (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",
};

在此範例中,measurement根據其值範圍進行分類。

分離 (or模式)

使用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}."),
};

在此,根據提供日期的月份確定日曆季節。

這些模式組合器可以反复使用以建立更復雜和精確的匹配條件,增強您的程式碼的靈活性和可讀性。

屬性模式

屬性模式使能夠將表達式的屬性或字段與巢狀模式匹配。 以下程式碼片段中可以看到一個例子:

static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };

在此,屬性模式確保提供的日期對應於指定的會議日之一。

您還可以在屬性模式中加入運行時型別檢查和變數聲明,如下所示:

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

在此,屬性模式用於處理字串和字元集合,確保根據其屬性進行適當處理。

位置模式

在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",
};

在此範例中,位置模式用於根據其座標分類點。

此外,您可以在屬性模式中引用巢狀的屬性或字段,稱為擴展屬性模式,首次在C# 10中引入:

static bool IsAnyEndOnXAxis(Segment segment) =>
    segment is { Start.Y: 0 } or { End.Y: 0 };

此功能增強了屬性模式的靈活性,允許直接存取巢狀屬性。

這些模式提供了強大的機制來處理復雜的資料結構,並改進了程式碼的可讀性和表達性。

Var模式

Var模式可讓您匹配任何型別。 這在捕獲布林表達式中的中間結果或需要在switch情況中的多次檢查時尤其有用。

以下是一個範例,展示了在布林表達式中使用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();
}

在此範例中,results中,允許根據其屬性進行後續計算。

此外,Var模式可以在switch表達式或語句中使用,以使程式碼更簡潔且更可讀。 以下是一個在switch情況守衛中使用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 }
}

在此範例中,Var模式(x, y)捕獲點的坐標,允許根據其值進行不同的轉換。

在Var模式中,所聲明變數的型別是從被匹配的表達式的編譯時型別推斷出的。

Var模式提供了一種便捷的方法來處理各種場景,其中表達式的具體型別預先未知,從而提高程式碼的清晰度和靈活性。

介紹IronPDF Library

IronPDF Document Rendering是來自Iron Software的庫,專注於PDF文件生成。 首先的步驟是從NuGet Package管理器或Visual Studio Package Manager中安裝此庫。

# To install from the NuGet Package Manager Console
Install-Package IronPdf
SHELL

下圖顯示了如何從Visual Studio 安裝指南中安裝。

C#模式匹配表達式(對於開發者的工作原理):圖1 - 使用NuGet包管理器安裝IronPDF

在以下程式碼中,我們將看到如何生成一個簡單的PDF文件:

using IronPdf;

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>Output: {(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: {season2}</p>";
            var season3 = GetCalendarSeason(new DateTime(2024, 7, 25));
            Console.WriteLine(season3);
            content += $"<p>2024, 7, 25: {season3}</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}."),
        };
    }
}

輸出

C#模式匹配表達式(對於開發者的工作原理):圖2

程式碼詳細資訊

此處我們使用IronPDF的ChromePdfRenderer類來將HTML字串保存為PDF文件。 輸出保存到"output.pdf"文件中。

試用授權

IronPDF可與從IronPDF授權頁面獲得的試用授權一起使用。 提供電子郵件地址以生成授權密鑰並發送至您的郵箱。

"IronPdf.LicenseKey": "<Your Key>"

將授權密鑰放置在appsettings.json文件中,如上所示。

結論

C#中的模式匹配表達式提供了一種強大而靈活的方式以精簡且易於理解的方法來寫條件語句、型別檢查和物件解構。 通過利用模式匹配,開發者可以提高程式碼的清晰度和可維護性,同時減少樣板程式碼和冗餘。 無論是型別檢查、switch語句還是解構,模式匹配表達式都為解決C#中各種編程任務提供了一套多用途的工具。

總之,精通模式匹配表達式可以極大地提高您的C#編程技能,使您能夠撰寫更清晰、更富有表現力的程式碼,且更易於理解和維護。 我們還涵蓋了IronPDF的HTML轉PDF生成能力,可以用於生成PDF文件。

Jacob Mellor,首席技術官 @ Team Iron
首席技術官

Jacob Mellor是Iron Software的首席技術官,一位在C# PDF技術上開創先河的遠見工程師。作為Iron Software核心程式碼庫的原開發者,他從創立以來就一直在塑造公司的產品架構,與首席執行官Cameron Rimington一起將公司轉變為服務於NASA、特斯拉和全球政府公司的50多名人員的公司。

...
閱讀更多

相關文章

Key in blue circle

立即免費取得 30 天試用金鑰。

Your trial license will be sent to your email address

無任何限制。100% 解鎖。無需信用卡。

OR
bullet_checked無需信用卡或建立帳號無任何限制。100% 解鎖。無需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried Iron Suite
預訂您的免費現場演示
Booking Badge

受到全球數百萬工程師的信任

Iron Software的客戶標誌
獲取您的無義務諮詢
填寫以下表格或電子郵件sales@ironsoftware.com
您的詳細資訊將始終保密。
受到全球數百萬工程師的信任
Iron Software的客戶標誌
立即獲取您的30天試用金鑰。
無需信用卡或帳戶建立
C# 用於PDF的NuGet程式庫
使用NuGet安裝

版本: 2026.9

PM > Install-Package IronPdf
nuget.org/packages/IronPdf/
  1. 在解決方案資源管理器,右鍵點選參考,管理NuGet包
  2. 選擇瀏覽並搜尋"IronPdf"
  3. 選擇套件並安裝
C# PDF DLL
下載DLL

版本: 2026.9

或者點擊此處下載Windows安裝程式。

  1. 下載並解壓IronPDF到類似~/Libs的位置,位於您的解決方案目錄中
  2. 在Visual Studio解決方案資源管理器,右鍵點選參考。選擇瀏覽,"IronPdf.dll"

授權從$999起