官方文档:析构元组和其他类型 - C# | Microsoft Learn

标签:Deconstruct、Tuple、record、模式匹配

PS:record相关内容后续还会继续更新🔄

模式匹配可以查看我的另一篇👉模式匹配

目录

    • 1. 概述
    • 2. 基本用法
      • 2.1 元组解构
      • 2.2丢弃符
    • 3. 进阶使用
      • 3.1 为自定义类型添加解构能力
          • 1. 为 `Person` 类实现解构
          • 2 扩展方法解构
      • 3.2 与记录(record) 的协同
      • 3.3 与模式匹配的联动(C# 8+)
    • 4. 限制与最佳实践
    • 5. 总结

1. 概述

Deconstruct(解构) 是 C# 7.0 引入的语法糖, 允许以简洁的语法从元组或对象中提取多个数据成员,避免逐个访问字段的繁琐操作。

它让元组、自定义类型、记录(record)等数据的“拆包”变得非常直观。

核心思想:将一个复合对象“拆分”成其组成部分。

关键词

  • Deconstruct 方法(实例或扩展方法)
  • 解构赋值(Deconstruction Assignment)
  • 丢弃符 _ (discard)
  • 元组 (T1, T2, …) 的隐式解构

2. 基本用法

2.1 元组解构

元组(Tuple)自带的解构支持是最直接的应用。

// 创建一个元组
var person = ("Alice", 30);
  1. 显式指定类型

    (string name1, int age1) = person; // 显式类型声明并解构
    
  2. 一次性声明并解构 (最常见)

    var (name2, age2) = person; // 使用 var 推断类型声明并解构
    

    也支持混合使用显式与 var 声明(但不建议):

    (string name3, var age3) = person;
    
  3. 析构到已声明的变量混合声明与赋值

    string name4 = "Eoch";
    (name4,  int age4) = person
    
  4. 变换:元组的解构与构造

    1. 构造 (Construction):等号右边 (b, a)构造一个新的元组,这个元组的两个元素分别是当前变量 ba 的值
    2. 解构 (Deconstruction):等号左边 (a, b)解构这个新元组,将其元素按顺序赋值给变量 ab
    int a = 5, b = 10;
    (a, b) = (b, a); // a 现在是 10, b 现在是 5
    

2.2丢弃符

在处理解构时,可能只对对象的一部分数据感兴趣。

C# 提供了 弃元(_ 来忽略不关心的输出参数,,其值将被忽略,使代码意图更清晰。

Person person = new Person("Bruce", "Banner", 40);// 只解构出 Age,忽略 FirstName 和 LastName
(_, _, int age) = person;// 或者,如果你只关心 LastName
(string _, string lastName, _) = person; // 第一个参数也用弃元Console.WriteLine(age); // 输出:40
Console.WriteLine(lastName); // 输出:Banner

3. 进阶使用

3.1 为自定义类型添加解构能力

要使你的自定义类或结构体能够被解构,你需要为其定义一个或多个 Deconstruct方法。

规则

  1. 方法名必须为 Deconstruct
  2. 方法必须是 public void
  3. 所有参数都必须使用 out 修饰符
  4. 参数的顺序和数量决定了你解构时变量的顺序和数量
1. 为 Person 类实现解构
public class Person
{public string FirstName { get; set; }public string LastName { get; set; }public int Age { get; set; }// 构造函数public Person(string firstName, string lastName, int age){FirstName = firstName;LastName = lastName;Age = age;}// 实现 Deconstruct 方法// 此方法允许将 Person 解构成 (firstName, lastName, age)public void Deconstruct(out string firstName, out string lastName, out int age){firstName = FirstName;lastName = LastName;age = Age;}// 重载:提供另一种解构方式,例如只解构出fullName、agepublic void Deconstruct(out string fullName, out int age){fullName = $"{FirstName} {LastName}";age = Age;}
}
2 扩展方法解构

// 1. 定义静态扩展类
public static class PersonExtensions
{// 2. 在扩展类中声明 Deconstruct 扩展方法。注意:必须是静态(static)且无返回值(void),所有要解构出的参数都使用 out 修饰符。public static void Deconstruct(this Person p,out string firstName,out string lastName,out int age){firstName = p.FirstName;lastName  = p.LastName;age       = p.Age;}// 3. 还可以再写其他重载public static void Deconstruct(this Person p,out string fullName,out int age){fullName = $"{p.FirstName} {p.LastName}";age      = p.Age;}
}

3.2 与记录(record) 的协同

录类型(record)天然支持基于位置参数的解构功能。

record Person(string FirstName, string LastName);var (f, l) = new Person("Ada", "Lovelace");

3.3 与模式匹配的联动(C# 8+)

从C# 8开始,解构功能与模式匹配语法深度集成,特别是在 switch 表达式中,可以直接对元组或可解构类型进行模式匹配。

例如:属性模式(property pattern)与位置模式(positional pattern)的结合使用。编译器会自动解构 Point 类型的坐标值,然后通过条件模式匹配进行判断。

static string Quadrant(Point p) => p switch
{( > 0, > 0) => "第一象限",( < 0, > 0) => "第二象限",_           => "其他"
};

4. 限制与最佳实践

  1. 命名一致性

    元组字段名与 Deconstruct 方法的 out 参数名无需强制一致,但保持命名一致性能显著提升代码的可读性和可维护性。

  2. 可空性处理

    当类型中的字段可能为 null 时,应在 Deconstruct 方法内部进行必要的空值防御性检查,并将对应的 out 参数类型标记为可空(如 out string? name)。

  3. 避免滥用

    解构虽方便,但过度使用会让代码意图变得模糊。应仅在能“明显提升可读性”的场景(如同时获取多个相关返回值)下使用,而非替代所有属性访问。

  4. out 参数的限制​

    在异步方法(标记为 async)中,不能使用 out 参数,因此也无法直接进行解构操作。

    常见的解决方法是先在同步代码中解构,将结果存入变量,再在异步方法中使用这些变量

    // 异步方法中无法直接解构:
    // var (name, age) = await GetPersonAsync(); // 错误// 解决方案:先同步获取对象,再解构
    var person = await GetPersonAsync();
    var (name, age) = person; // 正确
    

5. 总结

C# 的解构功能将对象(或元组)分解到一组独立的变量中,简化了从元组或对象中提取多个值的操作:

  • 元组析构:直接解包元组元素,支持类型推断和弃元_
  • 自定义类型析构:通过实现 Deconstruct 方法支持解构;
  • 扩展方法析构:为现有类型添加析构能力;
  • 集成使用:与元组、模式匹配、Record集成、适合变量交换及多返回值方法的调用场景。
  • 适合场景:适用于数据模型、DTO、坐标、元组等主要存储数据的简单对象。
Deconstruct
├── 内建:ValueTuple / record 位置参数
├── 自定义:实例方法 或 扩展方法 void Deconstruct(out T1, out T2, ...)
└── 语法形式:├─ var (a, b) = obj;├─ (int a, _) = obj;└─ switch 模式 (x, y)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/920787.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/920787.shtml
英文地址,请注明出处:http://en.pswp.cn/news/920787.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R 语言 ComplexUpset 包实战:替代 Venn 图的高级集合可视化方案

摘要 在生物信息学、数据挖掘等领域的集合分析中,传统 Venn 图在多维度数据展示时存在信息拥挤、可读性差等问题。本文基于 R 语言的 ComplexUpset 包,以基因表达研究为场景,从包安装、数据准备到可视化实现,完整演示如何制作正刊级别的集合交集图,解决多条件下差异基因(…

​导游|基于SprinBoot+vue的在线预约导游系统

在线预约导游系统 基于SprinBootvue的在线预约导游系统 一、前言 二、系统设计 三、系统功能设计 前台功能实现 后台功能实现 管理员模块实现 导游模块实现 用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&am…

SQL server 异常 出现错误 824

2025-08-27 01:36:37,324 ERROR c.z.i.w.DatabaseUtils [Scheduled-7] Error executeStoredProcedure SQL script: sp_RefreshDWDByDateFive警告: 在 08 27 2025 1:36AM 出现错误 824。请记录该错误和时间&#xff0c;并与您的系统管理员联系。 2025-08-27 01:36:37,332 ERROR …

制造业生产线连贯性动作识别系统开发

制造业生产线连贯性动作识别系统开发 第一部分&#xff1a;项目概述与理论基础 1.1 项目背景与意义 在现代智能制造环境中&#xff0c;尽管自动化程度不断提高&#xff0c;但人工操作仍然在复杂装配任务中扮演着不可替代的角色。研究表明&#xff0c;人机协作被视为打破传统人机…

什么是Jmeter? Jmeter工作原理是什么?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 第一篇 什么是 JMeter&#xff1f;JMeter 工作原理 1.1 什么是 JMeter Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具。用于对软件做压力测试&a…

Linux网络基础1(一)之计算机网络背景

文章目录计算机网络背景网络发展认识 "协议"高小琴例子方言例子计算机网络背景 网络发展 独立模式: 计算机之间相互独立; 网络互联: 多台计算机连接在一起, 完成数据共享; 局域网LAN: 计算机数量更多了, 通过交换机和路由器连接在一起; 广域网WAN: 将远隔千里的计算…

如何在数学建模赛中实现模型创新?

模型创新性在国赛数学建模中&#xff0c;完备性是论文的基本要求&#xff0c;而创新性则是决定论文能否脱颖而出的关键因素。所谓创新&#xff0c;并不仅仅指提出完全新颖的数学理论&#xff0c;而是能够在已有方法的基础上&#xff0c;通过新的问题切入点、假设修正、模型优化…

【重磅发布】flutter_chen_updater-版本升级更新

Flutter Chen Updater 一个功能强大的Flutter应用内更新插件&#xff0c;支持Android APK自动下载、安装和iOS跳转App Store。 ✨ 特性 ✅ 跨平台支持: Android APK自动更新&#xff0c;iOS跳转App Store✅ 智能下载: 支持断点续传、文件校验、多重备用方案✅ 权限管理: 自动处…

docker 1分钟 快速搭建 redis 哨兵集群

使用 docker-compose 1 分钟搭建好 1主2从3哨兵的 redis 哨兵集群 目录结构 redis-sentinel-cluster ├── check_redis.sh ├── docker-compose.yml ├── redis │ └── redis.conf ├── sentinel │ └── sentinel.confdocker-compose.yml 配置 version: 3…

Git与DevOps实战:从版本控制到自动化部署

一、版本控制1.什么是版本控制&#xff1f;版本控制用于高效追踪和管理项目开发中的代码、配置及文档变更历史&#xff0c;确保团队成员始终使用正确版本&#xff0c;并支持版本回溯、差异比较和文件恢复。它能带来以下优势&#xff1a;通过历史记录保障数据安全与完整性&#…

大模型——利用RAG构建智能问答平台实战

利用RAG构建智能问答平台实战 目前公司的智能问答平台利用RAG技术构建,现给大家分享下通RAG技术构建智能问平台的具体流程和原理。 一、什么是RAG RAG是检索增强生成技术(Retrieval-Augmented Generation),目前是构建智能问答的重要技术。RAG相比传统的检索可以可以减少…

flume事务机制详解:保障数据可靠性的核心逻辑

flume事务机制详解&#xff1a;保障数据可靠性的核心逻辑 在数据采集过程中&#xff0c;“不丢数据、不重数据” 是核心需求。Flume 之所以能在分布式环境下保证数据可靠性&#xff0c;关键在于其内置的事务机制。Flume 通过在 “Source → Channel” 和 “Channel → Sink” …

第四十九天(springboot模版注入ThymeleafFreemarkerVelocity)

开发框架-SpringBoot 参考&#xff1a;Spring Boot 中文文档 新建一个spring Boot 项目&#xff0c;修改服务器url为 aliyun.com 不然没有与jdk8版本对应的java 选择一个spring web 库&#xff0c;点击创建即可 来到这个页面点击运行 启动的是8080端口&#xff0c;用127.0.0.1…

Spring MVC 九大组件源码深度剖析(六):HandlerExceptionResolver - 异常处理的艺术

文章目录一、异常处理的核心价值二、核心接口设计三、四大内置实现类源码解析1. ExceptionHandlerExceptionResolver&#xff08;现代异常处理核心&#xff09;2. ResponseStatusExceptionResolver&#xff08;HTTP状态码处理&#xff09;3. DefaultHandlerExceptionResolver&a…

MCP(Model Context Protocol,模型上下文协议)介绍

1. 背景 随着大语言模型&#xff08;LLM, Large Language Model&#xff09;的应用越来越广泛&#xff0c;一个核心问题逐渐凸显&#xff1a; 模型在对话或推理时&#xff0c;往往只能依赖有限上下文窗口。外部工具、知识库、应用接口如何统一接入模型&#xff0c;缺乏标准协议…

synchronized的锁对象 和 wait,notify的调用者之间的关系

谁调用了wait和notify方法&#xff0c;会决定这两个方法的控制范围吗&#xff1f;你的问题非常深入&#xff0c;涉及到 wait() 和 notify() 方法的控制范围和作用域。让我们详细分析一下&#xff1a;✅ 核心概念&#xff1a;控制范围由“锁对象”决定wait() 和 notify() 的控制…

【技术教程】如何将文档编辑器集成到用 .Net 编写的网络应用程序中

在现代网络应用中&#xff0c;​富文本编辑能力已成为内容管理系统的核心需求。对于 .NET 开发者而言&#xff0c;选择适合的编辑器并高效集成&#xff0c;是构建企业级应用的关键一步&#xff0c;可让项目管理、 CRM 或定制化系统具备原生办公能力&#xff0c;消除频繁切换应用…

【大模型记忆-Mem0详解-1】概述

目的和能力 Mem0 通过提供以下功能将无状态 AI 应用程序转换为有状态、支持内存的系统&#xff1a; 持久记忆 &#xff1a;跨会话长期保留用户偏好、对话历史记录和上下文信息多级内存 &#xff1a;支持具有自适应个性化的用户级、会话级和代理级内存智能提取 &#xff1a;基于…

2024年山东省信息学小学组(CSP-X)第一轮题解

2024年山东省信息学小学组(CSP-X)第一轮题解 原题下载 单项选择题 阅读程序 阅读程序 #1 判断题 阅读程序 #2 判断题 单选题 阅读程序 #3 判断题 单选题 完善程序 消灭怪兽 位运算操作 原题下载 CSP-X2024小学组(山东)第一轮试题以及答案 单项选择题 共 15 题,每题 2 分…

SW - 用装配图的方式组合多个子零件然后转换成为零件,可维护性好

文章目录SW - 用装配图的方式组合多个子零件然后转换成为零件&#xff0c;可维护性好概述笔记例子将装配图另存为零件将零件图中的多个实体组合为一个实体的特征备注ENDSW - 用装配图的方式组合多个子零件然后转换成为零件&#xff0c;可维护性好 概述 以前画机械零件&#x…