• 分享C#14中的三个新特性
  • 发布于 19小时前
  • 12 热度
    0 评论
在本文中,我们将一起探索即将随 C# 14(对应 .NET 10)发布的一些新特性。目前这些功能已可在 .NET 10 预览版(Preview 3)和 Visual Studio 17.14 或更高版本的预览版中进行体验。本文将介绍以下几个亮点:
1.field 关键字
2.扩展成员(Extension Members)

3.空条件赋值(Null Conditional Assignment)


一、field 关键字:更优雅地实现属性封装逻辑
在早期的 C# 中,我们通常使用自动属性(Auto Properties):
public int Foo { get; set; }
如果需要在 get 或 set 中添加自定义逻辑,就得手动添加一个“后备字段”:
private int _foo;
publicint Foo
{
    get
    {
        // 执行某些逻辑
        return _foo;
    }
    set
    {
        // 额外逻辑
        _foo = value;
        // 更多逻辑
    }
}
虽然功能强大,但这种写法冗长。从 C# 14 开始,field 关键字带来了全新的简洁写法,允许你在不显式声明后备字段的情况下,编写带逻辑的属性访问器:
public int Foo
{
    get
    {
        // 自定义逻辑
        return field;
    }
    set
    {
        // 前置逻辑
        field = value;
        // 后置逻辑
    }
}
在编译时,field 会被自动替换为一个由编译器生成的后备字段,等价于:
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Foo>k__BackingField;
public int Foo
{
    get => <Foo>k__BackingField;
    set => <Foo>k__BackingField = value;
}
这种方式兼具可读性与灵活性,是自动属性与传统属性之间的理想折中方案。

二、扩展成员(Extension Members):不只是方法还能扩展属性!
扩展方法早已是 .NET 中的老朋友了,但你可能一直有个疑问:为什么不能为已有类型添加扩展“属性”?C# 14 引入的“扩展成员”语法,正是为解决这一痛点而来。传统扩展方法的写法如下:
internal sealedclassSpecialList<T>
{
    public List<T> Items { get; privateset; } = new();
    public void Add(T item) => Items.Add(item);
}
internalstaticclassExtensionMembers
{
    publicstaticvoid InsertOne<T>(this SpecialList<T> source, int index, T item)
    {
        if (index < 0 || index > source.Items.Count)
            thrownew ArgumentOutOfRangeException(nameof(index));

        source.Items.Insert(index, item);
    }
}
而 C# 14 引入的新写法更为直观:
internal staticclassExtensionMembers
{
    publicstaticvoid Insert<T>(this SpecialList<T> source, int index, T item)
    {
        if (index < 0 || index > source.Items.Count)
            thrownew ArgumentOutOfRangeException(nameof(index));
        source.Items.Insert(index, item);
    }
    publicstaticint Count<T>(this SpecialList<T> source) => source.Items.Count;
}
此外,C# 14 引入了新的 extension 块语法,进一步增强了功能:支持定义 静态扩展成员。
internal static class ExtensionMembers
{
    extension<T>(SpecialList<T>)
    {
        public static bool IsEmpty(IEnumerable<T> source) => !source.Any();
    }
}
这样你就可以直接通过类型调用扩展成员:
Console.WriteLine(SpecialList<int>.IsEmpty(new[] { 1, 2, 3 }));
示例用法:
var specialList = new SpecialList<int>();
specialList.Add(1);
specialList.Add(2);
specialList.Add(4);
// 堆代码 duidaima.com
// 调用扩展方法
specialList.Insert(2, 3);
specialList.InsertOne(2, 3);

foreach (var item in specialList.Items)
{
    Console.WriteLine(item);
}

Console.WriteLine($"Count: {specialList.Count}");
Console.WriteLine($"IsEmpty: {SpecialList<int>.IsEmpty(new int[] { 1, 2, 3 })}");
输出结果:
1
2
3
3
4
Count: 5
IsEmpty: False
三、空条件赋值(Null-Conditional Assignment):让空检查更优雅
作为 C# 开发者,你一定熟悉空条件操作符(?.):
foo?.Demo();
这段代码表示:仅当 foo 不为 null 时才调用 Demo() 方法。然而,如果我们想对一个对象的属性进行赋值操作,就不得不手动加判断:
if (foo is not null)
{
    foo.Bar = 20;
}
而在 C# 14 中,这种写法可以被简化为:
foo?.Bar = 20;
也就是说,只有在 foo 不为 null 时,Bar 才会被赋值为 20。该功能同样适用于复合赋值操作符,如 +=、-= 等:
foo?.Bar += 10;
这让代码更加简洁优雅。

总结
在本文中,我们探索了 C# 14 中的三个新特性:
1.使用 field 关键字简化属性封装
2.更强大的扩展成员语法支持方法和属性的扩展
3.更优雅的空条件赋值方式
这些新特性让 C# 在简洁性与功能性之间找到了更好的平衡,进一步提升了开发效率。接下来,我们还将继续探索 C# 14 中更多值得关注的新特性,敬请期待!
用户评论