C# 弃元的使用

news/2025/2/27 11:59:07/

总目录


前言

在C# 7.0及更高版本中,弃元(Discard)是一个新的语言特性,允许开发者在特定情况下忽略某些值。弃元用下划线 _ 作为占位符,明确表示忽略某个值,提升代码可读性


一、弃元是什么?

1. 基本概念

弃元(Discard)是 C# 7.0 引入的占位符变量,用下划线 _ 表示,用于显式声明某个值无需使用。它不会分配内存空间,甚至能减少编译器警告,让代码意图更明确。

  • 弃元是 C# 中的一个语言特性,用于在声明变量或表达式时显式地指定一个“不关心”的占位符。
  • 它使用下划线 _ 作为标识符,告诉编译器在这里不需要分配内存或存储数据,仅仅是为了语法的完整性而存在。
  • 从 C# 7.0 开始,C# 支持弃元,这是一种在应用程序代码中人为取消使用的占位符变量。 弃元相当于未赋值的变量;它们没有值。 因为只有一个弃元变量,甚至不为该变量分配存储空间,所以弃元可减少内存分配。 因为它们使代码的意图清楚,增强了其可读性和可维护性

2. 核心特性

  • 内存零分配:编译器不为弃元变量分配存储空间(弃元不存储值)
  • 意图明确化:明确告知开发者和编译器“此值无需使用”,编译器可能优化相关代码
  • 跨场景适配:适用于元组、模式匹配、异步编程等20+种场景

3. 注意事项

  1. 不可读取值:弃元 _ 一旦声明,后续代码中不能访问其值。

    var _ = 10;
    Console.WriteLine(_);  // 编译错误:弃元不可读取
    
  2. 作用域限制:同一作用域内 _ 只能作为弃元,不能重新定义为普通变量。

  3. var 的区别var 是类型推断,_ 是显式弃元。

二、弃元的使用

1. 元组和对象的析构

对于Deconstruct 不了解的,可以查看C# Deconstruct详解。

1)元组的析构

如果应用程序代码使用某些元组元素,但忽略其他元素,这时使用弃元来处理元组就会很有用

		// 使用弃元忽略元组中的第一个和第二个元素var(_,_,id) = ("jack","123",3);
        static void Main(string[] args){//通过使用 弃元,忽略age的值,只取name的值(var name, _) = GetUser();Console.WriteLine($"name:{name}");Console.ReadKey();}//该方法 返回类型为 元组 public static (string name, int age) GetUser(){return ("张三", 33);}

2)对象的析构

类、结构或接口的 Deconstruct 方法还允许从对象中检索和析构一组特定的数据。 如果想只使用析构值的一个子集,可使用弃元。

定义一个Person类,并在该类中定义了多个析构函数

	public class Person{public string FirstName { get; set; }public string MiddleName { get; set; }public string LastName { get; set; }public string City { get; set; }public string State { get; set; }//定义构造函数public Person(string fname, string mname, string lname,string cityName, string stateName){FirstName = fname;MiddleName = mname;LastName = lname;City = cityName;State = stateName;}// 定义析构函数public void Deconstruct(out string fname, out string lname){fname = FirstName;lname = LastName;}// 定义析构函数的重载public void Deconstruct(out string fname, out string mname, out string lname){fname = FirstName;mname = MiddleName;lname = LastName;}// 定义析构函数的重载public void Deconstruct(out string fname, out string lname,out string city, out string state){fname = FirstName;lname = LastName;city = City;state = State;}}

析构函数的运用,Person中有很多的属性,但是我只想取得其中部分属性的值:

	class Example{public static void Main(){var p = new Person("John", "Quincy", "Adams", "Boston", "MA");// 析构Person这个对象,并且只获取fName 和 city两个参数,其余的忽略var (fName, _, city, _) = p;Console.WriteLine($"Hello {fName} of {city}!");// Hello John of Boston!}}

2. 匹配模式中的弃元

    static void Main(){object obj = new int[] { 1, 2, 3 };switch (obj){case int[] _ when ((int[])obj).Length > 2:Console.WriteLine("数组长度大于2");break;case null:Console.WriteLine("空值");break;default:Console.WriteLine("其他类型");break;}}
    internal class MyClass{private int v1;private string v2;public MyClass(int v1, string v2){this.v1 = v1;this.v2 = v2;}}static void Main(string arg){object obj = new MyClass(10, "test");// 使用弃元忽略 MyClass 对象if (obj is MyClass _){Console.WriteLine("Matched MyClass type");}}

3. 异步方法中的弃元

明确表达“关注执行而非结果”

	// 异步执行且忽略返回值static void Main(){_ = Task.Run(() => Log("异步任务执行"));}public static void Log(string data){Console.WriteLine(data);}
    static void Main(string arg){_= GetResultAsync();  // 使用弃元忽略异步方法的结果}async static Task<int> GetResultAsync(){await Task.Delay(1000);return 10;}

4. out 参数与方法返回值

// 忽略 TryParse 的布尔返回值
int.TryParse("123", out _); // 忽略方法返回值
_ = GetConfig(); // 假设 GetConfig() 返回重要配置

注意:弃元不能读取值,否则会报错 CS0103

5. 迭代元素时的弃元

迭代元素时的弃元: 用于忽略迭代过程中的某些值。

var dictionary = new Dictionary<string, int>
{["apple"] = 1,["banana"] = 2,["cherry"] = 3
};// 使用弃元忽略键,只处理值
foreach (var (_, value) in dictionary)
{Console.WriteLine(value); // 输出:1 2 3
}

6. 独立弃元与空合并运算符

// 独立弃元:强制空值检查
_ = arg ?? throw new ArgumentNullException(); // 结合 null 合并运算符
var result = data ?? _ = LoadData(); 

场景

  • 防止空引用异常
  • 确保副作用(如 LoadData())被执行

弃元是 C# 提升代码简洁性的“语法糖”,通过合理使用下划线 _,能够帮助开发人员编写更为简洁和清晰的代码。通过使用弃元,可以有效地忽略不需要的变量或返回值,提高代码的可读性和维护性。在实际开发中,根据需要合理地运用弃元,可以使代码更加精简和易于理解。


结语

回到目录页:C# 知识汇总
以上就是本文的内容,希望以上内容可以帮助到您,如文中有不对之处,还请批评指正。


参考资料:
弃元 - C#指南
C# 弃元的详解与示例
MSDN弃元
MSDN析构元组


http://www.ppmy.cn/news/1575245.html

相关文章

AWS S3 如何设置公开访问权限?

1.让整个bucket都有公开访问权限 1.1关闭【阻止公共读】 1.2关闭ACL访问控制 1.3打开桶策略 这样桶内所有的图片就能访问了 2.只开放特定文件让其具有访问权限&#xff1f; 2.1关闭【阻止公共读】 如之前的图示 2.2打开ACL控制 2.3单个文件打开公共读

第二十六: 【存储+读取数据】

Store是一个保存&#xff1a;状态、业务逻辑 的实体&#xff0c;每个组件都可以读取、写入它。 它有三个概念&#xff1a;state、getter、action&#xff0c;相当于组件中的&#xff1a; data、 computed 和 methods。 具体编码&#xff1a;src/store/count.ts // 引入define…

车载DoIP诊断框架 --- 连接 DoIP ECU/车辆的故障排除

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

微软云和金山云和k8有什么区别

Kubernetes&#xff08;K8s&#xff09;和微软云&#xff08;Microsoft Cloud&#xff09;是两种不同的技术&#xff0c;分别用于不同的目的。Kubernetes是一个开源的容器编排系统&#xff0c;用于自动化部署、扩展和管理容器化应用程序&#xff0c;而微软云是一个提供多种云服…

js 判断数据是否为blob类型,blob数据转JSON和对象

判断数据是否为blob类型 function isBlob(obj) {return obj instanceof Blob; }blob数据转JSON和对象 let blob data;var reader new FileReader();reader.readAsText(blob, utf-8);reader.onload function (e) {let res JSON.parse(reader.result);}reader.onerror fun…

【十二】Golang 映射

&#x1f4a2;欢迎来到张胤尘的开源技术站 &#x1f4a5;开源如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 映射映射的定义映射初始化make 函数使用字面量 源…

MFC文件和注册表的操作

MFC文件和注册表的操作 日志、操作配置文件、ini、注册表、音视频的文件存储 Linux下一切皆文件 C/C操作文件 const char* 与 char* const const char* 常量指针&#xff0c;表示指向的内容为常量。指针可以指向其他变量&#xff0c;但是内容不能再变了 char szName[6]&qu…

Redis 缓存穿透、击穿、雪崩:问题与解决方案

在使用 Redis 作为缓存中间件时&#xff0c;系统可能会面临一些常见的问题&#xff0c;如 缓存穿透、缓存击穿 和 缓存雪崩。这些问题如果不加以解决&#xff0c;可能会导致数据库压力过大、系统响应变慢甚至崩溃。本文将详细分析这三种问题的起因&#xff0c;并提供有效的解决…