仅带吸气剂的自动属性,可以设置,为什么

本文关键字:属性 为什么 设置 | 更新日期: 2023-09-27 18:30:08

我创建了一个自动属性:

public int Foo { get; } 

这只是吸气剂。但是当我构建构造函数时,我可以更改值:

public MyClass(string name)
{
    Foo = 5;
}

为什么有可能,即使这是只得到的?

仅带吸气剂的自动属性,可以设置,为什么

这是一个新的 C# 6 功能,"仅 getter 自动属性",也称为"只读属性的自动属性初始值设定项",如 Mark Michaelis 的这篇 MSDN 杂志文章"C#:新的和改进的 C# 6.0"和 C# 6.0 草稿语言规范中所述。

只读字段的 setter 只能在构造函数中访问,在所有其他情况下,该字段仍然是只读的,并且行为与以前一样。

这是一种方便的语法,可减少需要键入的代码量,并消除显式声明私有模块级变量来保存值的需要。

自从在 C#3 中引入自动实现的属性以来,可变属性(具有 getter 和 setter 的属性(比不可变属性(只有 getter 的属性(编写得更快,这意味着人们很想使用可变属性来避免为只读属性通常需要的支持字段键入代码。 在 Microsoft C# 编程指南的相关部分中有更多关于自动实现属性的讨论。

肖恩·塞克斯顿(Sean Sexton(的这篇博客文章"#1,207 – C# 6.0 – 只读属性的自动属性初始值设定项"有一个很好的解释和示例,如下所示:

在 C# 6.0 之前,如果需要只读(不可变(属性,则需要 通常使用在 构造函数,如下所示。

public class Dog 
{
    public string Name { get; set; }
    // DogCreationTime is immutable
    private readonly DateTime creTime;
    public DateTime DogCreationTime 
    {
        get { return creTime; }
    }
    public Dog(string name)
    {
        Name = name;
        creTime = DateTime.Now;
    }
}

在 C# 6.0 中,可以使用自动实现的属性来实现 只读属性。 通过使用自动属性执行此操作 初始 化。 结果比上面的例子干净得多,其中 我们必须显式声明一个支持字段。

public class Dog
{
    public string Name { get; set; }
    // DogCreationTime is immutable
    public DateTime DogCreationTime { get; } = DateTime.Now;
    public Dog(string name)
    {
        Name = name;
    }
}

更多详细信息也可以在GitHub上的dotnet Roslyn存储库中找到:

现在可以在没有资源库的情况下声明自动属性。

仅 getter 自动属性的支持字段是隐式的 声明为只读(尽管这仅对反射很重要 目的(。它可以通过 属性如上例所示。此外,仅 getter 属性可以是 在声明类型的构造函数主体中赋值,这会导致 要直接分配给基础字段的值:

这是关于更简洁地表达类型,但请注意,它也 消除了可变和可变语言之间的重要差异 不可变类型:自动属性是仅在以下情况下可用的简写 你愿意让你的类可变,所以诱惑 默认为这很棒。现在,使用仅 getter 自动属性, 竞争环境在可变和不可变之间是平衡的。

在 C# 6.0 语言规范草案中(注意:就Microsoft而言,语言规范是最终的,但尚未被批准为 EMCA/ISO 标准,因此称为"草案"(:

自动实现的属性

自动实现的属性(或简称自动属性(是 具有仅分号访问器的非抽象非外部属性 机构。自动属性必须具有 get 访问器,并且可以选择 有一个设置的访问器。

将属性指定为自动实现的属性时, 隐藏的支持字段自动可用于属性, 并且实现访问器以读取和写入该 支持字段。如果自动属性没有设置访问器,则支持后盾 字段被视为只读(只读字段(。就像只读一样 字段中,也可以在正文中分配仅 getter 的自动属性 封闭类的构造函数。此类转让分配 直接转到属性的只读支持字段。

自动属性可以选择具有property_initializer,即 作为variable_initializer直接应用于背衬场 (变量初始值设定项(。

这是 C#6 中的一项新功能,允许您创建只读属性并从构造函数初始化其值(或在声明它们时内联(。

如果尝试在构造函数外部更改此属性的值,则会给出编译错误。

它是只读的,因为一旦初始化其值(内联或在构造函数内部(,就无法更改其值。

如果无法从构造函数(或自动属性初始值设定项(初始化只读属性,那么它将毫无用处,因为它将始终返回其类型的默认值(0 表示数字,null 表示引用类型(。相同的语义应用于所有 C# 版本中的只读字段。

要定义一个真正的仅 getter 属性(不能从构造函数初始化(,您需要指定它作为定义的一部分返回的内容:

public int Foo { get { return 5; } }

或者,在 C# 6 中更简洁地说:

public int Foo => 5;
">

只读自动实现的属性">

首先我想澄清一下,像这样的属性

public string FirstName { get; }

被称为"只读自动实现的属性">

要验证这一点,您可以使用Visual Studio运行并检查上述代码。如果将语言版本从 C#6.0 更改为 C#5.0,则编译器将引发以下异常功能"只读自动实现的属性"在 C# 5 中不可用。 请使用语言版本 6 或更高版本。

要更改 C# 语言版本,请访问此处

现在我来回答你的第二个问题

"这只是得到的。但是当我构建构造函数时,我可以更改值">

Microsoft在只读逻辑上引入了"只读自动实现的属性"。众所周知,关键字"readonly"可以从 C#1.0 获得。我们使用"readonly"关键字作为字段上的修饰符,该字段可以在声明时在同一类的构造函数中两种方式分配。

以同样的方式,可以通过两种方式分配"只读自动实现的属性"的值

方式1(申报时(:

public string FirstName { get; } = "Banketeshvar";

Way2(在同一类的构造函数中(

Person()
{
 FirstName  = "Banketeshvar";
}

纯只读属性

如果您正在寻找纯只读属性,那么请选择此属性

public string FullName => "Manish Sharma";

现在,您无法从构造函数中分配"全名"属性的值。如果您尝试这样做,它将引发以下异常

"属性或索引器'Person.FullName'不能分配给 - 它是只读的">

在 C# 3.0 发布期间,自动属性功能已添加到语言中。它允许您定义没有任何支持字段的属性,但是您仍然需要使用构造函数将这些自动属性初始化为非默认值。C# 6.0 引入了一个名为 auto 属性初始值设定项的新功能,它允许你在没有构造函数的情况下初始化这些属性,如下所示:

以前,如果要创建对象,则需要构造函数 使用自动属性并将自动属性初始化为 非默认值,如下所示:

public class MyClass
{
    public int Foo { get; }
    public Foo(int foo)
    {
        Foo = foo;
    }
}

现在在 C# 6.0 中,能够将初始值设定项与 auto 属性一起使用 表示不需要显式构造函数代码。

public string Foo { get; } = "SomeString";
public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };

您可以在此处找到更多信息

声明

readonly的变量可以在构造函数中编写,但在构造函数返回后不能使用遵循该属性的语言进行修改。 该限定符作为语言功能提供,因为对于值会根据构造函数参数而变化的字段通常是必需的(这意味着它们无法在构造函数启动之前初始化(,但在构造函数返回后不必更改,但它仅适用于作为字段公开的变量。 在许多情况下,readonly限定字段的语义对于公共成员来说是完美的,除了类通常最好将成员(甚至是不可变的成员(公开为属性而不是字段。

正如读写自动属性的存在允许类像普通字段一样轻松地公开可变属性一样

,只读自动属性的存在允许类像readonly限定字段一样轻松地公开不可变属性。 正如readonly限定字段可以在构造函数中编写一样,get-only 属性也是如此。