ZetCode

C# 解构

最后修改于 2025 年 5 月 14 日

本 C# 解构教程演示了如何将各种数据类型(例如元组、结构和类)中的变量解包为单独的组件,以便更方便地访问。

解构是将复杂类型分解为其组成部分的过程。 例如,可以将元组拆分为单独的元素,或者可以将对象解构为其属性,以便在代码中更轻松地处理。

C# 解构元组

在下一个示例中,我们将元组解构为项。

Program.cs
var user = ("John", "Doe", "gardener");

var (firstName, lastName, occupation) = user;

Console.WriteLine(firstName);
Console.WriteLine(lastName);
Console.WriteLine(occupation);

Console.WriteLine("-----------------");

var (fn, ln, oc) = getUser();

Console.WriteLine(fn);
Console.WriteLine(ln);
Console.WriteLine(oc);


(string, string, string) getUser()
{
    var fname = "John";
    var lname = "Doe";
    var occupation = "gardener";
    
    return (fname, lname, occupation);
}

用户元组有三个项; 这些项被解包到单独的变量中。

var (firstName, lastName, occupation) = user;

在这里,我们执行解构操作;

$ dotnet run
John
Doe
gardener
-----------------
John
Doe
gardener

丢弃可以用于不需要的项。

Program.cs
var user = ("John", "Doe", "gardener");
var (fname, lname, _) = user;

Console.WriteLine($"{fname} {lname}")

在此程序中,我们对第三个值使用丢弃。

C# 解构字典

字典由键/值对组成。 这些对可以被解包为两个单独的变量。

Program.cs
var domains = new Dictionary<string, string>
{
    {"sk", "Slovakia"},
    {"ru", "Russia"},
    {"de", "Germany"},
    {"no", "Norway"}
};

foreach ((string k, string v) in domains)
{
    Console.WriteLine($"{k}: {v}");
}

在 foreach 循环中,我们将每一对解包为 kv 变量。

$ dotnet run
sk: Slovakia
ru: Russia
de: Germany
no: Norway

C# 解构类

要解构类,我们必须实现 Deconstruct 方法。

Program.cs
var u = new User("John", "Doe", "gardener");
var (fname, lname, occupation) = u;

Console.WriteLine($"{fname} {lname} is a(n) {occupation}");

var (fn, ln) = u;
Console.WriteLine($"{fn} {ln}");


class User
{
    string FirstName { get; set; }
    string LastName { get; set; }
    string Occupation { get; set; }

    public User(string fname, string lname, string occupation)
    {
        FirstName = fname;
        LastName = lname;
        Occupation = occupation;
    }

    public void Deconstruct(out string fname, out string lname)
    {
        fname = FirstName;
        lname = LastName;
    }

    public void Deconstruct(out string fname, out string lname, 
        out string occupation)
    {
        fname = FirstName;
        lname = LastName;
        occupation = Occupation;
    }
}

我们可以有多个 Deconstruct 方法。

var u = new User("John", "Doe", "gardener");
var (fname, lname, occupation) = u;

在这里,我们将 User 类型解构为三个变量。

var (fn, ln) = u;
Console.WriteLine($"{fn} {ln}");

在这里,我们将用户解构为两个变量。

public void Deconstruct(out string fname, out string lname)
{
    fname = FirstName;
    lname = LastName;
}

被解构的变量具有 out 修饰符。

$ dotnet run
John Doe is a(n) gardener
John Doe

C# 解构结构

我们可以通过实现 Deconstruct 方法来解构自定义结构。

Program.cs
var point = new Point(5, 10);
var (x, y) = point;

Console.WriteLine($"x: {x}, y: {y}");

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 = X;
        y = Y;
    }
}

此示例演示了如何将结构解构为其字段。

C# 解构 KeyValuePair

可以使用 KeyValuePair 在 foreach 循环中直接解构字典条目。

Program.cs
var dict = new Dictionary<string, int> { {"apple", 3}, {"banana", 5} };

foreach (var (key, value) in dict)
{
    Console.WriteLine($"{key} => {value}");
}

在这里,每个键/值对在循环中被解包到单独的变量中。

C# 解构记录

具有位置参数的记录类型会自动解构; 编译器为我们创建 Deconstruct 方法。

Program.cs
var user = new User("John", "Doe", "gardener");
var (firstName, lastName, occupation) = user;

Console.WriteLine($"{firstName} {lastName} is a(n) {occupation}");

record User(string FirstName, string LastName, string Occupation);

在此示例中,我们解包 User 记录。

C# 解构扩展方法

在下一个示例中,我们将创建一个 Deconstruct 扩展方法。

Program.cs
var dt = new DateTime(2021, 9, 16);
(int year, int month, int day) = dt;

Console.WriteLine(year);
Console.WriteLine(month);
Console.WriteLine(day);

public static class MyExtension
{
    public static void Deconstruct(this DateTime dateTime, out int year,
        out int month, out int day)
    {
        year = dateTime.Year;
        month = dateTime.Month;
        day = dateTime.Day;
    }
}

该程序定义了 DateTime 类型的 Deconstruct 方法; 它将该类型解包为其年、月和日部分。

$ dotnet run
2021
9
16

来源

解构元组和其他类型

在本文中,我们介绍了 C# 中的解构操作。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直撰写编程文章。到目前为止,我已撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程