.NET10之C# Target-typed new expression深入解析

张开发
2026/4/3 11:06:32 15 分钟阅读
.NET10之C# Target-typed new expression深入解析
一、基本概念与语法目标类型 new()Target-typed new expression是 C# 9.0 引入的核心语言特性允许在目标类型已知的上下文中省略new关键字后的类型名称编译器会根据上下文自动推断要创建的对象类型。核心语法对比传统写法目标类型 new() 写法说明Listint list new Listint();Listint list new();无参构造函数Listint list new Listint(100);Listint list new(100);带参数构造函数Listint list new Listint { 1, 2, 3 };Listint list new() { 1, 2, 3 };对象/集合初始化器Dictionarystring, Listint dict new Dictionarystring, Listint();Dictionarystring, Listint dict new();复杂泛型类型关键规则必须有明确目标类型不能在var声明中使用new()因为目标类型未知// 错误无法推断类型// var list new();// 正确目标类型明确Listintlistnew();适用场景适用于所有有公共构造函数的引用类型和值类型枚举除外完整语法形式target_typed_new: new ( argument_list? ) object_or_collection_initializer?;二、解决的核心问题1. 消除类型重复提高代码简洁性在复杂类型初始化时无需重复冗长的类型名称尤其适用于嵌套泛型类型// 传统写法Dictionarystring,Dictionaryint,ListstringdatanewDictionarystring,Dictionaryint,Liststring();// 目标类型 new() 写法Dictionarystring,Dictionaryint,Liststringdatanew();2. 简化字段与属性初始化无需复制类型名称使代码更易维护减少拼写错误风险// 类中的字段初始化privatereadonlyDictionarystring,ListLogEntry_logsnew(){[Error]new(),[Warning]new(),[Info]new()};3. 优化方法参数传递当方法参数类型明确时可直接使用new()创建实例// 方法定义publicvoidProcessData(Optionsoptions){...}// 调用方法传统写法ProcessData(newOptions{Timeout30,RetryCount3});// 调用方法目标类型 new() 写法ProcessData(new{Timeout30,RetryCount3});4. 支持 throw 语句中的异常创建// 目标类型为 System.Exceptionthrownew();// 带参数的异常thrownew(Invalid operation,innerException);三、生产环境使用场景1. 集合与复杂对象初始化最常用在业务逻辑中创建各种集合类型尤其是在配置初始化、数据缓存等场景// 配置初始化varappSettingsnewAppSettings{ConnectionStringsnew(){[Default]Server...,[Redis]localhost:6379},Loggingnew(){LogLevelnew(){[Default]LogLevel.Information,[Microsoft]LogLevel.Warning}}};2. 依赖注入配置在 ASP.NET Core 等框架中配置服务时简化选项初始化// Startup.cs 或 Program.csbuilder.Services.ConfigureMvcOptions(options{options.Filters.Add(new()// 推断为 ServiceFilterAttribute{ServiceTypetypeof(ValidationFilter)});});3. 数据传输对象DTO创建在 API 开发中创建请求/响应对象减少重复代码// 创建订单请求varcreateOrderRequestnewCreateOrderRequest{CustomerIdCUST-123,Itemsnew(){new(){ProductIdPROD-456,Quantity2,UnitPrice19.99m},new(){ProductIdPROD-789,Quantity1,UnitPrice49.99m}},ShippingAddressnew(){Street123 Main St,CitySeattle,StateWA,PostalCode98101}};4. 单元测试中的对象构建在测试代码中快速创建测试数据提高可读性[Test]publicvoidCalculateTotal_WithDiscount_ReturnsCorrectValue(){// ArrangevarordernewOrder{Id1,CustomerIdCUST-123,Itemsnew(){new(){ProductNameLaptop,Price999.99m,Quantity1},new(){ProductNameMouse,Price29.99m,Quantity2}},Discountnew()// 推断为 PercentageDiscount{Rate0.1m// 10% 折扣}};// Actvartotalorder.CalculateTotal();// AssertAssert.AreEqual(999.99m29.99m*2-(999.99m29.99m*2)*0.1m,total);}5. 事件与委托处理在注册事件处理程序时简化委托实例创建// 声明事件publiceventEventHandlerDataReceivedEventArgsDataReceived;// 触发事件传统写法DataReceived?.Invoke(this,newDataReceivedEventArgs(data));// 触发事件目标类型 new() 写法DataReceived?.Invoke(this,new(data));6. 不可变类型与记录Record初始化C# 9.0 中的记录类型结合目标类型 new()使不可变对象创建更简洁publicrecordPerson(stringFirstName,stringLastName,intAge);// 创建记录实例Personpersonnew(John,Doe,30);// 使用 with 表达式创建新实例PersonupdatedPersonpersonwith{Age31};四、完整可运行代码示例以下是一个包含多种场景的完整示例可直接在 C# 9.0 环境中运行usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;// 1. 简单类型与集合初始化voidBasicUsage(){Console.WriteLine( 基本用法 );// 列表初始化Liststringfruitsnew(){Apple,Banana,Cherry};Console.WriteLine($Fruits:{string.Join(, ,fruits)});// 字典初始化Dictionaryint,stringnumberNamesnew(){[1]One,[2]Two,[3]Three};Console.WriteLine($Number 2:{numberNames[2]});// 带参数构造函数Listintnumbersnew(10);// 初始容量为 10numbers.AddRange(Enumerable.Range(1,5));Console.WriteLine($Numbers count:{numbers.Count}, Capacity:{numbers.Capacity});}// 2. 嵌套复杂对象voidNestedObjects(){Console.WriteLine(\n 嵌套对象 );varcompanynewCompany{NameTech Corp,Departmentsnew(){new(){NameEngineering,Employeesnew(){new(){Id1,NameAlice,PositionDeveloper},new(){Id2,NameBob,PositionDesigner}}},new(){NameSales,Employeesnew(){new(){Id3,NameCharlie,PositionSales Manager}}}}};Console.WriteLine($Company:{company.Name});foreach(vardeptincompany.Departments){Console.WriteLine($ Department:{dept.Name});foreach(varempindept.Employees){Console.WriteLine($ -{emp.Name}({emp.Position}));}}}// 3. 方法参数与异常处理voidMethodParametersAndExceptions(){Console.WriteLine(\n 方法参数与异常 );// 方法参数传递ProcessOrder(new(){OrderIdORD-789,Itemsnew(){new(){ProductIdPROD-100,Quantity2}}});// 异常抛出try{ValidateOrder(null);}catch(ArgumentNullExceptionex){Console.WriteLine($Caught expected exception:{ex.Message});}}// 辅助类定义publicclassCompany{publicstringName{get;set;}string.Empty;publicListDepartmentDepartments{get;set;}new();}publicclassDepartment{publicstringName{get;set;}string.Empty;publicListEmployeeEmployees{get;set;}new();}publicclassEmployee{publicintId{get;set;}publicstringName{get;set;}string.Empty;publicstringPosition{get;set;}string.Empty;}publicclassOrder{publicstringOrderId{get;set;}string.Empty;publicListOrderItemItems{get;set;}new();}publicclassOrderItem{publicstringProductId{get;set;}string.Empty;publicintQuantity{get;set;}}// 辅助方法publicstaticvoidProcessOrder(Orderorder){Console.WriteLine($Processing order:{order.OrderId});foreach(variteminorder.Items){Console.WriteLine($ Product{item.ProductId}:{item.Quantity}units);}}publicstaticvoidValidateOrder(Order?order){if(ordernull)thrownewArgumentNullException(nameof(order),Order cannot be null);}// 主程序publicclassProgram{publicstaticvoidMain(){BasicUsage();NestedObjects();MethodParametersAndExceptions();}}代码运行结果 基本用法 Fruits: Apple, Banana, Cherry Number 2: Two Numbers count: 5, Capacity: 10 嵌套对象 Company: Tech Corp Department: Engineering - Alice (Developer) - Bob (Designer) Department: Sales - Charlie (Sales Manager) 方法参数与异常 Processing order: ORD-789 Product PROD-100: 2 units Caught expected exception: Order cannot be null (Parameter order)四、最佳实践与注意事项1. 适用与不适用场景对比推荐使用场景不推荐/不适用场景字段/属性初始化尤其是复杂类型使用var声明变量时方法参数传递类型明确枚举类型无构造函数异常抛出throw new()接口类型无法直接实例化集合初始化List、Dictionary 等数组创建需要特殊语法嵌套对象创建动态类型dynamic2. 与 var 的区别特性目标类型 new()var类型推断方式从目标类型推断从右侧表达式推断适用场景目标类型明确时右侧类型明确时语法形式Type variable new();var variable new Type();可读性类型在左侧一目了然类型在右侧需查看3. 版本兼容性目标类型 new() 是C# 9.0 及以上版本的特性若需在旧版本项目中使用需升级项目的语言版本!-- .csproj 文件 --PropertyGroupLangVersion9.0/LangVersion/PropertyGroup五、总结目标类型 new() 是 C# 语言的重要改进它通过上下文类型推断消除了重复的类型名称使代码更加简洁、易读和易维护。在生产环境中它特别适合集合初始化、复杂对象创建、方法参数传递等场景能显著提高开发效率并减少错误。核心价值在保持类型安全的前提下平衡了代码简洁性与可读性是现代 C# 开发中不可或缺的语法糖。

更多文章