3

考虑类:

public class foo
{
    public object newObject
    {
        get
        {
            return new object();
        }
    }
}

根据 MSDN:

属性是提供灵活机制来读取、写入或计算私有字段值的成员。属性可以像公共数据成员一样使用,但它们实际上是称为访问器的特殊方法。这样可以轻松访问数据

和:

属性使类能够公开获取和设置值的公共方式,同时隐藏实现或验证代码。

get 属性访问器用于返回属性值,而 set 访问器用于分配新值。这些访问器可以具有不同的访问级别。有关详细信息,请参阅访问器辅助功能。

value 关键字用于定义由 set indexer 分配的值。

未实现 set 方法的属性是只读的。同时仍然提供方法的安全性和灵活性。

因此,这是否意味着在某个时间点 newObject 属性的值具有对返回的新对象的引用?

编辑从属性中删除只读

edit2还想澄清一下,这不是属性的最佳用途,而是尝试更有效地说明问题。

4

4 回答 4

10

每次访问属性时都会返回一个新对象,这不是属性的预期行为。相反,您应该每次都返回相同的值(例如,存储在字段中的值)。属性 getter 只是对返回值的方法的美化语法。你的代码编译成这样的(编译器通过在属性名称前加上前缀来创建一个 getter,get_然后作为 IL 发出):

public class foo
{
    public object get_newObject()
    {
        return new object();
    }
}

foo对 getter 的每次调用都会创建一个不知道或无法访问的新对象。

因此,这是否意味着在某个时间点 newObject 属性的值具有对返回的新对象的引用?

不。


使用支持字段的属性:

class Foo {

  readonly Object bar = new Object();

  public Object Bar { get { return this.bar; } }

}

使用自动属性:

class Foo {

  public Foo() {
    Bar = new Object();
  }

  public Object Bar { get; private set; }

}

使用与公共字段相同的简单语法访问属性。但是,通过使用属性,您可以向 getter 和 setter 添加代码,从而允许您在 getter 中进行延迟加载或在 setter 中进行验证(等等)。

于 2012-06-06T15:37:14.570 回答
1

在后台,您的属性将简单地调用一个名为 get_newObject() 的函数,如下所示:

public object get_newObject()
{
    return new object();
}

既然是这种情况,每次调用它总是会返回一个新对象。

如果您想保留对对象的引用,那么我建议创建一个私有字段来保存数据并让属性访问该字段,如下所示:

private object myObject;
public object newObject
{
    if(myObject == null)
    {
        myObject  = new object();
    }
    return myObject;
}

由于您的属性未定义集合,并且您的字段是私有的,因此 newObject 基本上在包含类之外。

于 2012-06-06T15:46:05.523 回答
1

C# 中的属性是“语法糖”。属性块内的代码get实际上是放入隐藏get_PropertyName()方法中,而set块​​中放入隐藏set_PropertyName()方法。对于您的代码,将创建以下方法:

public object get_newObject()
{
    return new object();
}

如果您使用 Reflector 或 ildasm 查看已编译的程序集,则可以看到这些隐藏的方法。

使用该属性时,C# 编译器会将您的属性的任何“get”访问转换为get_newObject()方法调用。举个例子:

如果您要编写以下内容:

var foo = new foo();
var aNewObject = foo.newObject;

编译器会将其转换为:

var foo = new foo();
var aNewObject = foo.get_newObject();

因此,在回答您的另一个问题时,当有人“获取”该属性时返回的新创建的对象不会存储在您的 foo 实例中,调用者每次都会简单地获取一个新对象。

于 2012-06-06T15:47:28.913 回答
0

不完全是。属性只是语法糖,因此您不必编写访问器方法(如 Java)。

所以这:

private int _myInteger;
public int MyInteger
{
    get { return _myInteger; }
    set { _myInteger = value; }
}

相当于这个:

private int _myInteger;
public int GetMyInteger()
{
    return _myInteger;
}

public void SetMyInteger(int value)
{
   _myInteger = value;
}

并且它变得更好,这也是等价的:

public int MyInteger { get; set; }
于 2012-06-06T15:38:30.700 回答