2008-12-04 78 views

回答

49

错误:属性或索引器不可能会作为传出或引用参数

传递如果没有指定{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 
    } 
} 

你不应该创建公共字段/于类变量,你永远不知道什么时候你会想改变它有让&组访问,然后你不知道你要什么码打破,特别是如果你有客户对您的API进行编程。

另外,您可以为get &集合设置不同的访问修饰符,例如, {得到; private set;}使get public和set为private声明类。

62

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

public int Foo { get; private set; } 

或者只写属性:

public int Foo { private get; set; } 
+3

您还可以添加各种修饰符,如受保护等。 – Tigraine 2008-12-04 13:15:42

+0

是的,还有其他人说的......您需要一种方法来区分字段和属性。 – 2008-12-04 13:19:50

+1

有点旁注:有只读字段的概念。该框架将确保这些只写入一次。它与私人制片人或获得者不同,如果你有权限的话可以写出来。 – 2008-12-04 13:24:38

4

编译器需要知道,如果你想让它生成getter和/或一个二传手,或者可能正在宣布一个领域。

16

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

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

public int MyProperty { get; private set; } 
2

如果该属性没有访问器,编译器如何将它与字段分开?什么将它与田地分开?

16

只是想我会分享我对这个主题的发现。

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

public int MyProperty { get; set; } 

这可以为您节省一些打字费用。申报财产的很长的路是这样的:

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

当您使用“自动实现的属性”,编译器生成的代码线了get和set一些“k_BackingField”。下面是使用反射器的反汇编代码。

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

拆卸C#代码从IL

另外导线开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#代码

在声明只读自动实现的属性,通过设置器,以私人:

public int MyProperty { get; private set; } 

所有的编译器标志“ “作为私人。 setter和getter方法也是一样的。

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

从IL拆卸C#代码

所以我不知道为什么需要框架将Get;并设置;在自动实施的财产上。如果没有提供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; 
} 

拆卸C#从IL

2

好代码,显然,你需要字段和属性之间的多义性的一种方式。但是必需的关键字是否真的有必要例如,很明显,这两个声明是不同的:

public int Foo; 
public int Bar { } 

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

但是,你会遇到空块具有语义含义的情况。这似乎不稳定。

2

由于没有人提到它...你可以做自动虚拟财产和重写它:

public virtual int Property { get; set; } 

如果没有的get/set,如何将它被覆盖?请注意,您被允许override the getter and not the setter

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

而且,因为自从C#6.0(在Visual Studio 2015年,在这个答案在版本最终预览可用时),你可以实现一个真正的只读属性:

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

...相对于目前的解决方法不完善与公共的吸气/私人设定器对:

public string Name { get; private set; } 

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

低于上述实施例(编译和executa ble online here)。

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可作为官方预览视频here

相关问题