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。