C# 13 Preview 的 field keyword

科技   2024-11-15 08:02   广东  

C# 13 Preview 的 field keyword

Intro

C# 13 将以预览版的特性推出 field keyword 特性,等了几年的功能终于要能用上了,目前在最新版本的 VS 预览版本(17.12.0 Preview 3)中已经可用,不过可惜的是 .NET 9 RC 2 SDK 还不支持,得等到 .NET 9 正式版本了

Sample

field keyword 特性是指在属性(Property)的上下文中支持使用 field 关键词来引用属性背后的字段

我们来看下自动属性的示例:

public string Name { getset; }

这等同于

private string _name;
public string Name
{
    get => _name;
    set => _name = value;
}

使用 field 关键词改一下如下:

public string Name
{
    get => field;
    set => field = value;
}

再来看一个实际一点使用示例:

internal static class FieldKeywordSample
{
    public static string Name
    {
        get;
        set => field = value?.Trim() ?? string.Empty;
    } = string.Empty;
}

这个示例我们每次对 setter 做了一个 Trim() 的操作,并且保证不给 field 设置 null, null 时设置为 string.Empty

这在之前版本我们就得先声明成下面这样:

internal static class FieldKeywordSample
{
    private static string _name;
    public static string Name
    {
        get => _name;
        set => _name = value?.Trim() ?? string.Empty;
    } = string.Empty;
}

需要声明这个字段并且 getter 也需要写完整,即使没有特殊逻辑直接返回了字段

使用 field 关键词之后就无需声明字段了,并且如果是直接返回或者设置 value 就可以使用自动属性的写法,如下:

public int Num { get => field > 0 ? field : 0set; }
public int Num2 { getset => field = value > 0 ? value : 0; }

所以之前这个功能也被称为半自动属性,public string Name { get; set; } 则是完全自动属性

除了这样 getter/setter 直接使用,我们也可以在 getter 返回之前、setter set 之前以及之后做一些自定义的操作,如下:

internal static class FieldKeywordSample
{
    public static string Name
    {
        get;
        set => field = value?.Trim() ?? string.Empty;
        //set;
    } = string.Empty;

    public static string Description
    {
        get => field ?? string.Empty;
        set
        {
            Console.Write(">>>");
            Console.WriteLine(field);
            Console.WriteLine($"Before set description, {nameof(value)}{value}");
            field = value?.Trim()!;
            // CS0103: The name 'field' does not exist in the current context
            // Console.WriteLine($"After set description, {field}");
            Console.WriteLine("After set description");
            Console.Write(">>>");
            Console.WriteLine(field);
        }
    } = default!;

    public static void Run()
    {
        Name = " Hello ";
        Console.WriteLine(Name);
        Console.WriteLine(Name.Length);

        Console.WriteLine(Description is not null);
        Description = " World ";
        Console.WriteLine(Description);
        Console.WriteLine(Description.Length);
    }
}

输出结果如下:

output


反编译


More

需要注意,想要体验这个特性的话需要将 LangVersion 设置为 preview 才可以。

注意前面的代码的话会看到注释里有一个 error,当在插值字符串中使用 field 关键词的时候会报错

已经有 PR 在修这个问题了 https://github.com/dotnet/roslyn/pull/75566

dotnet-exec 的预览版本中也支持了这一特性,从这个特性合并到 main 分支开始就在等待发布新的 Roslyn nuget 包

但是一直没有更新,所以后面使用了 Roslyn 的 daily build 版本,额外添加了一个 nuget source  https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json,感兴趣的话可以看看 nuget.config https://github.com/WeihanLi/dotnet-exec/blob/main/nuget.config

使用下面这个命令来安装 dotnet-exec tool 来体验,因为还是预览版特性,需要使用  --preview option 来使用这个特性

dotnet tool update -g dotnet-execute --prerelease

References

  • https://github.com/dotnet/csharplang/blob/main/proposals/field-keyword.md
  • https://github.com/dotnet/csharplang/issues/140
  • https://github.com/dotnet/roslyn/pull/75566
  • https://github.com/WeihanLi/SamplesInPractice/blob/main/net9sample/CSharp13Samples/FieldKeywordSample.cs
  • https://github.com/WeihanLi/dotnet-exec/blob/main/nuget.config


推荐阅读:
.NET 9正式发布,亮点是.NET Aspire和AI
今晚零点!一同相约 .NET Conf 2024
适用于 .NET 稳定的官方OpenAI库
.NET无侵入式对象池解决方案
相约 .NET 9!|共同关注 .NET Conf 2024 最新发布
在 .NET 中编写更好的配置文件

点击下方卡片关注DotNet NB

一起交流学习

▲ 点击上方卡片关注DotNet NB,一起交流学习

请在公众号后台

回复 【路线图】获取.NET 2024开发者路线
回复 【原创内容】获取公众号原创内容
回复 【峰会视频】获取.NET Conf大会视频
回复 【个人简介】获取作者个人简介
回复 【年终总结】获取作者年终回顾
回复 加群加入DotNet NB 交流学习群

长按识别下方二维码,或点击阅读原文。和我一起,交流学习,分享心得。

DotNet NB
.NET 技术学习分享,社区热点分享,专注为 .NET 社区做贡献,愿我们互相交流学习,共同推动社区发展
 最新文章