C#自动属性 ​​- 为什么我必须写“get; 组;”?

如果在C#自动属性中都强制使用get和set,为什么还要指定“get; set” 在所有?

错误:属性或索引器不能作为out或refparameter passing

如果你没有指定{get; set;} {get; set;}那么编译器将不知道它是一个字段或属性。 这是非常重要的,因为当他们“看起来”相同时,编译器会以不同的方式对待它们。 例如在属性上调用“InitAnInt”会引发错误。

 class Test { public int n; public int i { get; set; } public void InitAnInt(out int p) { p = 100; } public Test() { InitAnInt(out n); // This is OK InitAnInt(out i); // ERROR: A property or indexer may not be passed // as an out or ref parameter } } 

你不应该在类上创build公共字段/variables,你永远不知道什么时候你想要改变它以获取和设置访问器,然后你不知道什么代码会打破,特别是如果你有针对您的API进行编程的客户端。

你也可以为get&set设置不同的访问修饰符,例如{get; 私人设置;}使公开和私人集声明类。

因为您可能需要一个只读属性:

 public int Foo { get; private set; } 

或只写属性:

 public int Foo { private get; set; } 

因为你需要一些方法来区分它与普通的领域。

有不同的访问修饰符也是有用的,例如

 public int MyProperty { get; private set; } 

只是想我会分享我关于这个话题的发现。

编码如下属性,是一个.net 3.0快捷方式调用“ 自动执行的属性 ”。

 public int MyProperty { get; set; } 

这可以节省您一些打字。 申报财产的漫长过程就是这样的:

 private int myProperty; public int MyProperty { get { return myProperty; } set { myProperty = value; } } 

当你使用“自动实现的属性”时,编译器会生成连接get的代码并将其设置为某个“k_BackingField”。 下面是使用reflection器的反汇编代码。

 public int MyProperty { [CompilerGenerated] get { return this.<MyProperty>k__BackingField; } [CompilerGenerated] set { this.<MyProperty>k__BackingField = value; } } 

从IL反汇编的C#代码

同时为setter和getter提供一个方法。

 [CompilerGenerated] public void set_MyProperty(int value) { this.<MyProperty>k__BackingField = value; } [CompilerGenerated] public int get_MyProperty() { return this.<MyProperty>k__BackingField; } 

从IL反汇编的C#代码

当您声明只读自动实现的属性时,通过将setter设置为private:

  public int MyProperty { get; private set; } 

所有的编译器确实将“ set ”标记为私有的。 setter和getter方法也是一样的。

 public int MyProperty { [CompilerGenerated] get { return this.<MyProperty>k__BackingField; } private [CompilerGenerated] set { this.<MyProperty>k__BackingField = value; } } 

从IL反汇编的C#代码

所以我不知道为什么框架要求得到; 并设置; 在一个自动实施的财产。 如果没有提供set和setter方法,他们可能不会写。 但是,可能有一些编译器级别的问题,这使得这个困难,我不知道。

如果你看看声明只读属性的很长的路要走:

 public int myProperty = 0; public int MyProperty { get { return myProperty; } } 

然后看看反汇编的代码。 二传手根本就没有。

 public int Test2 { get { return this._test; } } public int get_Test2() { return this._test; } 

从IL反汇编的C#代码

编译器需要知道你是否想要它产生一个getter和/或setter,或者可能是声明一个字段。

如果财产没有访问者,那么编译器如何将它与领域分离? 什么将它从一个领域分开?

那么,显然你需要一个消除字段和属性之间的歧义的方法。 但是必要的关键字是否真的有必要 例如,很明显,这两个声明是不同的:

 public int Foo; public int Bar { } 

这可以工作。 也就是说,这是编译器可以想象的语法。

但是,你会遇到一个空块有语义的情况。 这似乎岌岌可危。

由于没有人提到它…你可以使自动属性虚拟并覆盖它:

 public virtual int Property { get; set; } 

如果没有得到/设置,将如何被覆盖? 请注意,您可以重写getter而不是setter :

 public override int Property { get { return int.MinValue; } } 

此外,因为从C#6.0开始(在Visual Studio 2015中,在Ultimate Preview版本中提供此答案时),您可以实现一个真正的只读属性:

 public string Name { get; } public string Name { get; } = "This won't change even internally"; 

…与公共的getter / private setter配对相比,目前还不完善的解决方法:

 public string Name { get; private set; } public Constructor() { Name="As initialised"; } public void Method() { Name="This might be changed internally. By mistake. Or not."; } 

上面的例子(在线编译和执行)

 using System; public class Propertier { public string ReadOnlyPlease { get; private set; } public Propertier() { ReadOnlyPlease="As initialised"; } public void Method() { ReadOnlyPlease="This might be changed internally"; } public override string ToString() { return String.Format("[{0}]",ReadOnlyPlease); } } public class Program { static void Main() { Propertier p=new Propertier(); Console.WriteLine(p); // p.ReadOnlyPlease="Changing externally!"; // Console.WriteLine(p); // error CS0272: The property or indexer `Propertier.ReadOnlyPlease' cannot be used in this context because the set accessor is inaccessible // That's good and intended. // But... p.Method(); Console.WriteLine(p); } } 

其他关于C#6.0的美味新闻可以在这里作为官方预览video。