只有getter的自动属性,可以设置,为什么?

时间:2016-01-12 12:20:14

标签: c# c#-6.0

我创建了一个自动化属性:

public int Foo { get; } 

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

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

为什么有可能,即使这只是get-only?

6 个答案:

答案 0 :(得分:109)

这是一个新的C#6功能,"仅限Getter的自动属性",也称为"用于只读属性的自动属性初始化器"正如本MSDN magazine article 'C# : The New and Improved C# 6.0' by Mark MichaelisC# 6.0 draft Language Specification中所述。

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

这是一种方便的语法,可以减少您需要输入的代码量,并且无需显式声明私有模块级变量来保存该值。

此功能被认为是重要的,因为在C#3中引入了自动实现的属性,可变属性(具有getter和setter的属性)比不可变属性(仅具有getter的那些)更快地编写,意味着人们试图使用可变属性来避免必须为只读属性通常需要的支持字段键入代码。 relevant section of the Microsoft C# Programming Guide中有更多关于自动实现属性的讨论。

This blog post, '#1,207 – C# 6.0 – Auto-Property Initializers for Read-Only Properties' by Sean Sexton有一个很好的解释和示例如下:

  

在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;
    }
}

更多细节也可以在the dotnet Roslyn repo on GitHub中找到:

  

现在可以在没有设置器的情况下声明自动属性。

     

仅具有getter的自动属性的支持字段是隐式的   宣称为只读(虽然这只是反思   目的)。它可以通过初始化器初始化   如上例所示的属性。此外,只有吸气剂属性可以   在声明类型的构造函数体中赋值,这会导致   值直接分配给基础字段:

     

这是关于更简洁地表达类型,但请注意它   消除了mutable和。之间语言的重要区别   不可变类型:auto-properties只有在可用的简写时才可用   你愿意让你的班级变得可变,所以诱惑   默认为那很棒。现在,只有getter-auto属性,   在可变和不可变之间已经达到了公平的竞争环境。

C# 6.0 draft Language Specification(注意:就微软而言,语言规范是最终的,但它是yet to be approved as a EMCA/ISO standard,因此'草稿'):

  

自动实施的属性

     

自动实现的属性(或简称自动属性)是   非抽象非外部属性,仅使用分号访问器   身体。自动属性必须具有get访问器,并且可以选择   有一套访问者。

     

将属性指定为自动实现的属性时,   隐藏的支持字段可自动用于该属性,   并且实现访问器以读取和写入访问器   支持领域。如果auto-property没有set访问器,则支持   字段被认为是只读(只读字段)。就像一个只读   字段,也可以在正文中分配仅限getter的自动属性   封闭类的构造函数。这样的任务分配   直接到属性的只读后备字段。

     

自动属性可以选择具有property_initializer,即   作为variable_initializer直接应用于支持字段   (可变初始化器)。

答案 1 :(得分:24)

这是a new feature in C#6,它允许您创建只读属性并从构造函数初始化它们的值(或在声明它们时内联)。

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

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

答案 2 :(得分:15)

如果无法从构造函数(或自动属性初始值设定项)初始化只读属性,那么它将无用,因为它总是返回其类型的默认值(0表示数字,null供参考类型)。所有C#版本中的readonly字段都使用相同的语义。

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

public int Foo { get { return 5; } }

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

public int Foo => 5;

答案 3 :(得分:5)

“只读自动实施的属性”

首先,我想澄清像

这样的属性
public string FirstName { get; }

被称为“只读自动实现的属性”

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

更改C#语言版本访问here

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

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

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

同样,“只读自动实现的属性”的值可以用两种方式分配

Way1(声明时):

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

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

Person()
{
 FirstName  = "Banketeshvar";
}

Purely ReadOnly Property

如果您正在寻找纯粹的Readonly属性,请转到此

public string FullName => "Manish Sharma";

现在你不能从构造函数中赋予“FullName”值的值。 如果您尝试这样做,则会抛出以下异常

“无法将属性或索引器'Person.FullName'分配给 - 它只读”

答案 4 :(得分:4)

在C#3.0版本中,自动属性功能已添加到语言中。它允许您定义没有任何支持字段的属性,但是您仍然需要使用构造函数将这些自动属性初始化为非默认值。 C#6.0引入了一个名为auto property initializer的新功能,它允许您初始化这些属性而无需像下面这样的构造函数:

  

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

public class MyClass
{
    public int Foo { get; }

    public Foo(int foo)
    {
        Foo = foo;
    }
}
  

现在在C#6.0中,能够使用具有auto-property的初始化程序   意味着不需要显式的构造函数代码。

public string Foo { get; } = "SomeString";

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

You can find more information on this here

答案 5 :(得分:1)

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

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