C# 属性是隐藏实例变量还是更深层次的事情
本文关键字:深层次 变量 属性 隐藏 实例 | 更新日期: 2023-09-27 18:36:32
考虑类:
public class foo
{
public object newObject
{
get
{
return new object();
}
}
}
根据MSDN:
属性是提供灵活读取机制的成员,写入或计算私有字段的值。可以使用属性好像他们是公共数据成员,但实际上他们很特殊称为访问器的方法。这使得数据能够轻松访问
和:
属性使类能够公开获取和设置值,同时隐藏实现或验证码。
get 属性访问器用于返回属性值,而set 访问器用于分配新值。这些访问器可以具有不同的访问级别。有关详细信息,请参阅访问器可及性。
value 关键字用于定义由设置索引器。
不实现 set 方法的属性是只读的。同时仍然提供方法的安全性和灵活性。
因此,这是否意味着在某个时间点,newObject 属性的值具有对返回的新对象的引用?
编辑从属性中删除的只读内容
edit2 还想澄清一下,这不是属性的最佳用途,但它是为了尝试更有效地说明问题。
每次访问属性时都会返回一个新对象,这不是属性的预期行为。相反,您应该每次都返回相同的值(例如,存储在字段中的值)。属性 getter 只是返回值的方法的美化语法。您的代码编译成这样的东西(编译器通过在属性名称前面加上 get_
来创建 getter,然后作为 IL 发出):
public class foo
{
public object get_newObject()
{
return new object();
}
}
每次调用 getter 都会创建一个foo
不知道或有权访问的新对象。
因此,这是否意味着在某个时间点,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 中进行验证(以及更多)之类的操作。
在后台,您的属性将简单地调用一个名为 get_newObject() 的函数,如下所示:
public object get_newObject()
{
return new object();
}
由于是这种情况,因此每次调用它时,它总是会返回一个新对象。
如果要保留对对象的引用,那么我建议您创建一个私有字段来保存数据,并让属性访问该字段,如下所示:
private object myObject;
public object newObject
{
if(myObject == null)
{
myObject = new object();
}
return myObject;
}
由于您的属性没有定义 set,并且您的字段是私有的,因此 newObject 基本上只在包含类之外
C# 中的属性是"语法糖"。属性的get
块中的代码实际上放入隐藏get_PropertyName()
方法中,set
块放入隐藏set_PropertyName()
方法中。对于您的代码,将创建以下方法:
public object get_newObject()
{
return new object();
}
如果使用反射器或 ildasm查看已编译的程序集,则可以看到这些隐藏的方法。
使用该属性时,C# 编译器会将属性的任何"get"访问转换为 get_newObject()
方法的调用。举个例子:
如果您要编写以下内容:
var foo = new foo();
var aNewObject = foo.newObject;
编译器会将其转换为:
var foo = new foo();
var aNewObject = foo.get_newObject();
因此,在回答您的另一个问题时,当有人"获取"属性时返回的新创建的对象不会存储在您的 foo 实例中,调用方每次都会简单地获取一个新对象。
不完全是。属性只是语法糖,因此您不必编写访问器方法(如 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; }