这是否会破坏拥有只读属性的整个目的?

flo*_*ode 10 c# properties

我知道如何使用属性,我理解他们隐含地调用底层getset访问器,这取决于我们是写入还是读取属性.

static void Main(string[] args)
{
    A a = new A();
    (a.b).i = 100;

}

class A 
{
    private B _b = new B();
    public B b
    {
        get { return _b; }
    }
}
class B  
{
    public int i;
}
Run Code Online (Sandbox Code Playgroud)

代码(a.b).i = 100;基本上是第一个属性的get访问者返回对象的引用_b,一旦我们有了这个引用,我们就能够访问_b’s成员并更改它们的值.

因此,在我们的示例中,具有只读属性仅防止外部代码更改引用变量的值_b,但它不会阻止外部代码访问_b’s成员.

因此,似乎属性只能检测我们是否正在尝试读取或写入_b位于堆栈上的变量(在我们的案例变量中),而它无法检测我们是否也尝试写入对象的成员堆栈上的变量(假设此变量是引用类型)指向的.

a)但这不能破坏拥有只读属性的整个目的吗?如果属性能够检测我们是否正在尝试访问由get访问器返回的对象的成员(假设支持字段是引用类型),那会不会更有效?

谢谢

pli*_*nth 27

不变性不是传递性的; 你不能指望可变对象成为不可变的访问器是不可变的.

  • 我喜欢这个答案,但问题意味着缺乏对可变性的理解,所以我不确定它是多么有用. (5认同)

And*_*wis 19

您的参考是只读的,而不是您的对象.


Joe*_*orn 13

想象一下这样的一个类:

public class A
{
    private List<int> _myList<int> = new List<int>();
    public List<int> MyList { get { return _myList; } }
}
Run Code Online (Sandbox Code Playgroud)

现在,该类的用户可以添加和删除并访问列表中的项目,但它们无法替换列表本身.这个很重要.它允许你在类中做一些事情,例如假设_myList成员永远不为null.

换句话说,这个范例允许您在类中定义一个接口,以便用户可以使用您公开的属性中的类型,但是它们不能只是从您下面交换复杂类型的实例.


Bri*_*ian 9

  1. 不,它没有破坏只读属性的目的.
  2. 可以使用不允许用户更改基础数据的只读属性.例如,System.Collections.ObjectModel.ReadOnlyCollection即使基础类型是a ,您也可以让属性返回List.这当然不会阻止用户更改项目性质集合.


sim*_*sjo 6

当然你可以访问B.i; 它是public.您认为既然_b是私有的,所有方法在获取时都应该是私有的A?在那种情况下,它是无用的,因为你无法B用于任何事情.


Dan*_*Tao 5

你问:

难道这不会破坏拥有只读属性的整个目的吗?

但是看:你的B.i成员是一个公共领域.

那么我问:拥有公共领域的目的是什么?只有您希望代码的用户能够更改该字段的值才有意义.如果你希望出现这种情况,应该是一个私有字段,或者(如果你想提供读不能写访问)有私人属性访问器.set

所以有你的答案.private B _b在你贴得很好(代码提供它的目的_b就无法从外部设置到新的东西),正如public int i供应目的同样好(i 可以从外部改变).