【问题标题】:How to declare a C# Record Type?如何声明 C# 记录类型?
【发布时间】:2017-03-29 23:23:35
【问题描述】:

我读到 on a blog 说 C# 7 将具有记录类型

class studentInfo(string StudentFName, string StudentMName, string StudentLName);

但是当我尝试它时,我得到了这些错误

CS0116 命名空间不能直接包含成员,例如字段或 方法
CS1022 类型或命名空间定义,或预期文件结尾
CS1514 { 预期的

这应该如何工作?

更新:这是 C# 9 的一个特性 https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/

【问题讨论】:

标签: c# language-features c#-7.0


【解决方案1】:

更新:

C# 9 now contains record types.

public record Person
{
    public string LastName { get; }
    public string FirstName { get; }

    public Person(string first, string last) => (FirstName, LastName) = (first, last);
}

旧答案:

C# 中还没有(还)实现记录类型。请参阅官方 GitHub 存储库中的提案:

https://github.com/dotnet/csharplang/blob/master/proposals/records.md

https://github.com/dotnet/csharplang/issues/39讨论或投票

【讨论】:

  • @JeremyThompson 我猜有人标记了它?不是我,我经历了我的历史,但它不存在。也许是编辑它的人?这真的很重要吗?
  • 此 c# 9 功能是否在任何 .NET 5 预览版中都可用?
  • @IainGalloway 至少是 .NET 5.0 RC 1 尽管使用 record 语法而不是旧的 data class 提议。在LINQPad6 中,您甚至可以在不安装 .net 5 的情况下摆弄 C# 9(如果您安装了 .net core 3.1 - 该功能需要 5 或 3.1)。从 6.10 发行说明:只需转到编辑 | Preferences > Query 并勾选 Enable C# 9 Preview 复选框。
【解决方案2】:

记录类型在 C# 7.0 的路线图上,但最终推迟到该语言的更高版本。

引用 Mads Torgersen 回复this blog post

[Primary constructors] 仍然受到关注,以及记录类型的相关概念(我们在 C# 7.0 中考虑过),我希望我们能够找到更好的设计 -或许两者兼而有之。

在 C# 7 发布时,此语言功能的 GitHub proposal 仍表示实现是“进行中”。

【讨论】:

【解决方案3】:

[重写以反映事物的当前状态]

要添加到其他答案,您可以轻松跟踪这些天 C# 功能何时出现在 C# 中。例如,Champion "Records" 问题显示了围绕记录思考的状态。 Records 现在计划用于 C# 9。但该功能之前也被吹捧为 C# 6、C# 7 和 C# 8,因此它仍然只是一个愿望。

【讨论】:

    【解决方案4】:

    在 C# 7.0 之前,您可以像这样声明类:

    虽然记录类型尚未在 C# 7.0 中实现(如其他答案所述),但您可以使用 C# 6.0 中引入的read-only auto-properties 缩短代码:

    public class studentInfo
    {
        public string StudentFName { get; }
        public string StudentMName { get; }
        public string StudentLName { get; }
    
        public studentInfo(string strFN, string strMN, string strLN)
        {
            StudentFName = strFN;
            StudentMName = strMN;
            StudentLName = strLN;
        }
    }
    

    【讨论】:

    • 不幸的是,这要求每个成员写三次(作为属性,作为构造函数参数,以及作为构造函数中的赋值)。我建议将来使用 T4 生成这些不可变的 POCO(以帮助防止在构造函数中没有正确分配的错误)。
    • @Dai:后两者可以使用 Visual Studio 的"Generate constructor" quick action 自动化。也就是说,我也期待摆脱所有样板代码并拥有“真实”的记录类型。
    【解决方案5】:

    如果您正在寻找使用当前可用的 C# 7 功能实现构造函数的类似记录的惰性方法,则有一种方法:

    class Lazystructor
    {
        int a;
        float b;
        WebClient c;
    
        public Lazystructor(int a, float b, WebClient c)
            =>  (this.a, this.b, this.c) = (a, b, c);
    }
    

    如果您在性能敏感的场景中使用它,请考虑一下,因为它是一个 ValueTuple 创建和提取的过程。

    【讨论】:

    • 这很有创意。
    • 我会给你一个关于创造力的更新,但我不喜欢这种语法。记录的全部意义在于简化简单类型的声明,但我认为人们会觉得这很混乱。
    【解决方案6】:

    现在可以使用 C#9 并使用它进行记录。

    这里有一些例子:

    public record Person
    {
        public string LastName { get; init; }
        public string FirstName { get; init; }
    
        public Person(string first, string last) => (FirstName, LastName) = (first, last);
    }
    

    使用位置记录(和继承):

    public record Teacher(string FirstName, string LastName,
        string Subject)
        : Person(FirstName, LastName);
    
    public sealed record Student(string FirstName,
        string LastName, int Level)
        : Person(FirstName, LastName);
    
    var person = new Person("Bill", "Wagner");
    
    var (first, last) = person;
    Console.WriteLine(first);
    Console.WriteLine(last);
    

    最后,记录支持 with 表达式。 with 表达式指示编译器创建记录的副本,但修改了指定的属性:

    Person brother = person with { FirstName = "Paul" };
    

    您需要了解的有关每个新功能的所有信息,包括记录here

    【讨论】:

    • 只有链接的答案最终会出现在时间机器上。如果您追求积分/代表,请花时间在未来几年写一个体面的答案。
    猜你喜欢
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多