实用指南:C# 14 新特性详解

C# 14 新特性详解

1. 概述

C# 14 是与 .NET 10 一同发布的最新主要版本,引入了多项新功能来提升开发效率和代码表达能力。这些新特性包括扩展成员、field 关键字、隐式跨度转换、未绑定泛型类型支持等。

2. 扩展成员 (Extension Members)

2.1 扩展属性和索引器

C# 14 引入了新的扩展成员语法,不仅支持扩展方法,还支持扩展属性和索引器:

public static class EnumerableExtensions
{
// 扩展块 - 为实例成员扩展
extension(IEnumerable source)
{
// 扩展属性
public bool IsEmpty => !source.Any();
// 扩展索引器
public TSource this[int index] => source.Skip(index).First();
// 扩展方法
public IEnumerable Where(Func predicate)
{
// 实现...
}
}
// 扩展块 - 为静态成员扩展
extension(IEnumerable)
{
// 静态扩展方法
public static IEnumerable Combine(
IEnumerable first,
IEnumerable second)
{
// 实现...
}
// 静态扩展属性
public static IEnumerable Identity => Enumerable.Empty();
}
}

2.2 使用示例

var sequence = new List { 1, 2, 3 };
// 调用扩展属性(实例成员)
bool isEmpty = sequence.IsEmpty;
// 调用扩展索引器
int item = sequence[1];
// 调用静态扩展属性
var identity = IEnumerable.Identity;
// 调用静态扩展方法
var combined = IEnumerable.Combine(sequence, new[] { 4, 5 });

3. field 关键字

3.1 简化属性实现

field 关键字允许编写属性访问器而无需显式声明后备字段:

// 传统方式
private string _message;
public string Message
{
get => _message;
set => _message = value ?? throw new ArgumentNullException(nameof(value));
}
// C# 14 方式
public string Message
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(value));
}

3.2 使用场景

// 只读属性
public string Name { get => field; private set => field = value; }
// 带验证的属性
public int Age
{
get => field;
set => field = value >= 0 ? value : throw new ArgumentException("Age cannot be negative");
}
// 带日志的属性
public string Status
{
get => field;
set
{
Console.WriteLine($"Status changing from {field} to {value}");
field = value;
}
}

4. 隐式跨度转换

4.1 跨度类型转换增强

C# 14 为 Span<T>ReadOnlySpan<T> 提供了更好的隐式转换支持:

// 数组到 Span 的隐式转换
Span span = new int[] { 1, 2, 3, 4, 5 };
// 数组到 ReadOnlySpan 的隐式转换
ReadOnlySpan readOnlySpan = new int[] { 1, 2, 3, 4, 5 };
// Span 到 ReadOnlySpan 的隐式转换
ReadOnlySpan readOnlyFromSpan = span;
// 字符串到 ReadOnlySpan 的隐式转换
ReadOnlySpan charSpan = "Hello World";

4.2 实际应用

public static void ProcessData(ReadOnlySpan data)
{
// 处理数据...
foreach (var item in data)
{
Console.WriteLine(item);
}
}
// 可以直接传入不同类型的参数
ProcessData(new int[] { 1, 2, 3 });           // 数组
ProcessData(stackalloc int[] { 1, 2, 3 });   // 栈分配数组

5. 未绑定泛型类型和 nameof

5.1 nameof 支持未绑定泛型

// C# 14 新特性
string name1 = nameof(List<>);        // 返回 "List"
string name2 = nameof(Dictionary); // 返回 "Dictionary"
// 早期版本需要关闭的泛型类型
string name3 = nameof(List);     // 返回 "List"

5.2 实际应用场景

public static void LogGenericType()
{
Console.WriteLine($"Processing type: {nameof(T)}");
}
// 使用示例
LogGenericType>();  // 输出: Processing type: List

6. 带修饰符的简单 Lambda 参数

6.1 Lambda 参数修饰符支持

现在可以在不指定参数类型的情况下为 lambda 参数添加修饰符:

delegate bool TryParse(string text, out T result);
// C# 14 方式 - 简化的参数声明
TryParse parse1 = (text, out result) => int.TryParse(text, out result);
// 传统方式 - 需要完整类型声明
TryParse parse2 = (string text, out int result) => int.TryParse(text, out result);

6.2 支持的修饰符

// ref 修饰符
delegate void ModifyValue(ref int value);
ModifyValue modifier = (ref int x) => x *= 2;
// in 修饰符(只读引用)
delegate void ReadValue(in int value);
ReadValue reader = (in int x) => Console.WriteLine(x);
// scoped 修饰符
delegate void ScopedOperation(scoped ReadOnlySpan span);
ScopedOperation operation = (scoped ReadOnlySpan data) =>
{
// 处理数据...
};

7. Partial 构造函数和事件

7.1 Partial 构造函数

public partial class Person
{
// 构造函数定义声明
public partial Person(string name, int age);
// 构造函数实现声明
public partial Person(string name, int age)
{
Name = name;
Age = age;
}
}
public partial class Person
{
public string Name { get; }
public int Age { get; }
}

7.2 Partial 事件

public partial class EventPublisher
{
// 事件定义声明
public partial event EventHandler MessageReceived;
// 事件实现声明
public partial event EventHandler MessageReceived
{
add { /* 添加事件处理程序 */ }
remove { /* 移除事件处理程序 */ }
}
}

8. 用户自定义复合赋值运算符

8.1 自定义复合赋值

public class Counter
{
public int Value { get; set; }
// 用户定义的复合赋值运算符
public static Counter operator +=(Counter left, int right)
{
left.Value += right;
return left;
}
public static Counter operator -=(Counter left, int right)
{
left.Value -= right;
return left;
}
}
// 使用示例
var counter = new Counter { Value = 10 };
counter += 5;  // Value 现在是 15
counter -= 3;  // Value 现在是 12

9. Null 条件赋值

9.1 简化 Null 检查

// C# 14 之前的方式
if (customer != null)
{
customer.Order = GetCurrentOrder();
}
// C# 14 方式 - Null 条件赋值
customer?.Order = GetCurrentOrder();

9.2 复合赋值支持

// 支持复合赋值运算符
customer?.Balance += 100;
customer?.Items?.Add(newItem);
// 不支持递增和递减运算符
// customer?.Count++;  // 编译错误
// customer?.Count--;  // 编译错误

9.3 短路求值

public class ExpensiveOperation
{
public static string GetExpensiveResult()
{
Console.WriteLine("执行昂贵操作");
return "Result";
}
}
// 只有在 customer 不为 null 时才会执行 GetExpensiveResult()
customer?.Description = ExpensiveOperation.GetExpensiveResult();

10. 最佳实践和注意事项

10.1 扩展成员使用建议

// 好的做法:为相关功能分组
extension(IEnumerable source)
{
public bool IsNullOrEmpty => source == null || !source.Any();
public T SecondOrDefault() => source.Skip(1).FirstOrDefault();
}
// 避免:过度使用扩展成员导致 API 混乱

10.2 field 关键字注意事项

public class Example
{
// 当存在同名符号时,需要消除歧义
private string field = "instance field";
public string Property
{
get => @field;  // 或 this.field
set => @field = value;
}
}

10.3 性能考虑

// 利用 Span 的隐式转换提高性能
public static void ProcessString(ReadOnlySpan text)
{
// 避免不必要的字符串分配
for (int i = 0; i

11. 总结

C# 14 引入了以下主要新特性:

  1. 扩展成员:支持扩展属性、索引器和静态扩展成员
  2. field 关键字:简化属性实现,无需显式声明后备字段
  3. 隐式跨度转换:增强 Span 和 ReadOnlySpan 的使用体验
  4. 未绑定泛型支持:nameof 操作符支持未绑定泛型类型
  5. Lambda 参数修饰符:简化 lambda 参数声明
  6. Partial 构造函数和事件:支持分部构造函数和事件声明
  7. 用户自定义复合赋值:允许自定义复合赋值运算符
  8. Null 条件赋值:简化 Null 检查和赋值操作

这些新特性使 C# 代码更加简洁、表达力更强,同时保持了类型安全和性能优势。开发者应该根据具体场景合理使用这些新功能,以提高代码质量和开发效率。

posted @ 2025-09-11 10:30  wzzkaifa  阅读(445)  评论(0)    收藏  举报