我创建了一个自动化属性:
public int Foo { get; }
这只是吸气剂.但是当我构建一个构造函数时,我可以更改值:
public MyClass(string name) { Foo = 5; }
为什么有可能,即使这只是获取?
这是一个新的C#6功能,"仅限Getter的自动属性",也称为"只读属性的自动属性初始化器",正如本MSDN杂志文章"C#:The New and Improved C#6.0"中所述. Michaelis和C#6.0草案语言规范.
只读字段的setter只能在构造函数中访问,在所有其他方案中,该字段仍然是只读的,并且行为与以前一样.
这是一种方便的语法,可以减少您需要键入的代码量,并且无需显式声明私有模块级变量来保存该值.
这个特性被认为是重要的,因为在C#3中引入自动实现的属性,可变属性(具有getter和setter的属性)比不可变属性(仅具有getter的那些)更快地编写,这意味着人们是试图使用可变属性来避免必须为只读属性通常需要的支持字段键入代码.有关自动实现属性的更多讨论,请参阅Microsoft C#编程指南的相关部分.
此博客文章"#1,207 - C#6.0 - 只读属性的自动属性初始化程序"作者: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; } }
更多细节也可以在GitHub上的dotnet Roslyn repo中找到:
现在可以在没有setter的情况下声明自动属性.
仅具有getter的自动属性的支持字段被隐式声明为readonly(尽管这仅用于反射目的).它可以通过属性上的初始化程序进行初始化,如上例所示.此外,可以在声明类型的构造函数体中指定仅getter属性,这会将值直接分配给基础字段:
这是关于更简洁地表达类型,但请注意,它还消除了可变类型和不可变类型之间语言的重要区别:只有当您愿意使您的类变为可变时,自动属性才是可用的简写,因此默认的诱惑这很棒.现在,使用仅限getter的自动属性,可变和不可变之间的游戏场已经被平衡.
并且在C#6.0草案语言规范中(注意:就微软而言,语言规范是最终的,但它尚未被批准为EMCA/ISO标准,因此是"草案"):
自动实现的属性
自动实现的属性(或简称auto-property)是一个非抽象的非extern属性,只有分号的访问器体.自动属性必须具有get访问器,并且可以选择具有set访问器.
将属性指定为自动实现的属性时,将为该属性自动提供隐藏的后备字段,并且实现访问器以读取和写入该后备字段.如果auto-property没有set访问器,则支持字段被认为是readonly(只读字段).就像一个只读域,只有消气自动特性也可在封闭类的构造函数体内赋值.这样的赋值直接分配给属性的只读后备字段.
auto-property可以选择性地具有property_initializer,它作为variable_initializer(Variable initializers)直接应用于支持字段.
这是C#6中的一个新功能,它允许您创建只读属性并从构造函数初始化它们的值(或在声明它们时内联).
如果您尝试在构造函数外部更改此属性的值,则会出现编译错误.
它是只读的,一旦你初始化它的值(内联或在构造函数内),你就无法改变它的值.
如果无法从构造函数(或自动属性初始化程序)初始化只读属性,那么它将是无用的,因为它总是返回其类型的默认值(0表示数字,null表示引用类型).相同的语义应用于所有C#版本中的只读字段.
要定义一个真正的getter-only属性(无法从构造函数初始化),您需要指定它作为定义的一部分返回的内容:
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在只读逻辑上引入了“自动实现的只读属性”。众所周知,C#1.0提供了关键字“只读”。我们在字段上使用“只读”关键字作为修饰符,并且可以在声明时或在同一类的构造函数中以两种方式分配该字段。
以相同的方式,可以通过两种方式分配“只读自动实现的属性”的值
Way1(在声明时):
public string FirstName { get; } = "Banketeshvar";
Way2(在同一类的构造函数中)
Person() { FirstName = "Banketeshvar"; }
纯只读属性
如果您正在寻找纯粹的只读属性,那么为此
public string FullName => "Manish Sharma";
现在,您不能从构造函数分配“ FullName”属性的值。如果您尝试这样做,它将抛出以下异常
“无法将属性或索引器'Person.FullName'分配给它-只读”