从C# 1.0到12.0我是如何用这些新特性重构了十年前的老项目代码的接手一个十年前用C# 2.0编写的库存管理系统时我仿佛打开了时间胶囊。那些充斥着ArrayList和手动字符串拼接的代码像是一本泛黄的编程教科书。但这次我决定不再做考古学家——而是用现代C#的特性为这套系统进行一次彻底的技术换血。1. 从类型混乱到强类型安全老项目的DataAccess.cs文件里随处可见这样的代码public ArrayList GetProducts(int categoryId) { ArrayList list new ArrayList(); SqlCommand cmd new SqlCommand(SELECT * FROM Products WHERE CategoryIDcid); cmd.Parameters.Add(cid, SqlDbType.Int).Value categoryId; using (SqlDataReader dr cmd.ExecuteReader()) { while (dr.Read()) { Hashtable item new Hashtable(); item[ID] dr[ProductID]; item[Name] dr[ProductName]; // 20多个字段的重复劳动... list.Add(item); } } return list; }1.1 泛型集合与自动属性首先用C# 2.0就引入的ListT替换ArrayList配合C# 3.0的自动属性public class Product { public int Id { get; set; } public string Name { get; set; } // 其他属性... } public ListProduct GetProducts(int categoryId) { var products new ListProduct(); // 查询逻辑... }1.2 Dapper简化数据访问结合微ORM工具Dapper代码简化为public IEnumerableProduct GetProducts(int categoryId) { using var conn new SqlConnection(_connString); return conn.QueryProduct( SELECT ProductID as Id, ProductName as Name FROM Products WHERE CategoryIDcid, new { cid categoryId }); }提示C# 8.0的using声明语法让资源管理更直观无需嵌套代码块2. 空引用异常的系统性歼灭老代码中约30%的bug报告都与NullReferenceException有关。C# 8.0的可空引用类型成为了我们的核武器#nullable enable public class Order { public int OrderId { get; set; } public string CustomerName { get; set; } // 编译警告非空属性未初始化 public string? DiscountCode { get; set; } // 明确声明可为null } // 调用时强制空值检查 void ProcessOrder(Order order) { Console.WriteLine(order.CustomerName.Length); // 安全访问 if (order.DiscountCode ! null) { Console.WriteLine(order.DiscountCode.Length); // 安全访问 } }配合C# 6.0的null条件运算符decimal? discount order?.DiscountCode?.Length 0 ? CalculateDiscount(order.DiscountCode) : null;3. 模式匹配改造业务逻辑原来的价格计算逻辑充斥着if-else和类型检查public decimal CalculatePrice(object item) { if (item is Product) { var p (Product)item; return p.BasePrice * (1 p.TaxRate); } else if (item is Service) { var s (Service)item; return s.HourlyRate * s.EstimatedHours; } // 更多条件分支... }用C# 7.0的模式匹配重写public decimal CalculatePrice(object item) item switch { Product { IsOnSale: true } p p.BasePrice * 0.9m, Product p p.BasePrice * (1 p.TaxRate), Service { EstimatedHours: 10 } s s.HourlyRate * s.EstimatedHours * 0.85m, Service s s.HourlyRate * s.EstimatedHours, Bundle b b.Items.Sum(CalculatePrice), _ throw new ArgumentException(未知商品类型) };4. 不可变数据模型的进化之路原来的DTO类充斥着可变状态导致并发问题public class Customer { public int Id { get; set; } public string Name { get; set; } // 50多个可写属性... }4.1 C# 9.0记录类型改造成不可变模型public record Customer( int Id, string Name, // 其他属性... Address PrimaryAddress) { public string DisplayName ${Name} ({Id}); }4.2 非破坏性修改使用with表达式创建修改后的副本var updatedCustomer originalCustomer with { Name 新客户名称, PrimaryAddress originalCustomer.PrimaryAddress with { City 新城市 } };5. 现代字符串处理技巧老代码中的字符串拼接像是一场噩梦string message 客户 customer.Name 的订单 order.Id 总金额为 order.Total.ToString(C) 。;5.1 字符串插值C# 6.0的字符串插值string message $客户 {customer.Name} 的订单 {order.Id} 总金额为 {order.Total:C}。;5.2 原始字符串字面量C# 11的多行字符串处理string json { id: {order.Id}, customer: {customer.Name}, total: {order.Total} } ;6. 异步化改造实战原来的同步IO操作导致UI冻结public void GenerateReport(string path) { var data GetReportData(); // 同步调用 using (var writer new StreamWriter(path)) { writer.Write(data); // 同步写入 } }6.1 异步流处理使用C# 8.0异步流public async IAsyncEnumerableReportItem StreamReportDataAsync() { using var conn new SqlConnection(_connString); await foreach (var item in conn.QueryAsyncReportItem(...)) { yield return item; } }6.2 并行处理优化结合C# 4.0的并行库和C# 5.0的async/awaitpublic async Task ProcessBatchAsync(IEnumerableint ids) { var tasks ids.Select(async id { var data await FetchDataAsync(id); return TransformData(data); }); var results await Task.WhenAll(tasks); await SaveResultsAsync(results); }重构后的代码库体积减少了40%性能提升了3倍而最宝贵的是——新团队成员不再需要解密祖传代码就能快速上手。每次提交代码时我都能感受到C#语言设计者的智慧结晶正在我们的项目中持续发光发热。