假设你有一个属性:
Person person1;
public Person Captin{
get{
return person1;
}
set{
person1 = value;
}
}
public void SomeFunction(){
Captin.name = "Hook"
}
在这种情况下,如果您在属性上设置名称,我们就知道Hook的新名称将应用于person1的基础值。如果我们的实施有点不同,请说:
public Person Captin{
get{
return ReadCaptinFromDisk();
}
set{
WriteCaptinToDisk(value);
}
}
public void SomeFunction(){
Captin.name = "Hook"
}
在这种情况下,要正确设置基础值,我们需要将Captin的设置代码作为Captin.name赋值的一部分。
我很想知道参数集代码是否会在属性引用的字段或方法调用的赋值上调用set。特别是对于需要将值传播到磁盘(等)的这种情况。
答案 0 :(得分:4)
每次访问属性Captin时,它都会从磁盘读取。但是如果更改属性“name”,它将不会写入磁盘。如果您执行类似
的操作,它只会写入磁盘public void SomeFunction() {
Person p = Captin;
p.name = "Hook";
Captin = p;
}
答案 1 :(得分:1)
@Joe注意到它不会写入磁盘。我只是想补充一点,因为你只使用了getter,而不是setter。 @ Joe的例子使用了两者。
在我看来,这对吸气剂的使用非常糟糕,并且违反了关注点的分离。您应该有一个处理持久化数据的数据层。这个逻辑不应该在你的业务对象中。
答案 2 :(得分:1)
只有当某人实际直接分配时,才会调用该属性的setter。
至于你的代码是否合适:这是一个文档问题。
每当你有一个返回可变的东西的属性时,你应该指出它会发生什么样的突变。您是否正在返回“真实”数据的副本,还是真正的数据本身?当属性(或普通方法)返回某种类型的集合时,这种情况经常出现 - 它是可变的吗?如果我改变它会发生什么?
如果您记录您的财产,说明返回的数据只是一个副本,并且更改不会反映在任何地方,那很好。如果你不明确,那就是你会遇到问题。
当然,不变性消除了这些顾虑......
答案 3 :(得分:1)
类型变量,参数,字段,返回值或其他此类存储位置应被视为持有“对象ID”。如果某个对象Foo
具有某个类类型的Bar
属性,该属性由字段_Bar
支持,而_Bar
包含“对象ID#24601”,那么语句{ {1}}将调用对象#24601上的Foo.Bar.Text = "George"
setter,其值为“George”。请注意,此语句不会修改对象Text
本身(其字段Foo
将在语句执行之前保留“对象ID#24601”,并且仍会保留它);但是,它可能会影响对象#24601。
结构类型存储位置应该被认为是保存其所有字段(公共和私有)的内容。如果_Bar
是Foo.Boz
类型(结构)和支持字段Rectangle
的属性,则对_Boz
的访问将创建类型为{{1}的新临时实例},所有字段都将从Foo.Boz
的字段中复制。尝试阅读Rectangle
会将Foo._Boz
的所有字段复制到临时实例,然后访问该实例的字段Foo.Boz.X
。
请注意,一些真正古老而邪恶的C#编译器会将_Boz
之类的代码解释为X
,丢弃结果值temp但不发出任何警告。这种编译器行为导致一些人声明结构应该是“不可变的”,以确保这样的代码将生成编译器错误而不是产生伪造的行为。不幸的是,尽管任何体面的编译器都会禁止这样的代码,即使Foo.Boz.X = 5;
是一个可变字段,这种信念仍然存在。
请注意,更新可变结构类型属性的正确方法是:
Rectangle temp = MyListOFRectangles[5]; temp.X = 5; MyListOFRectangles[5] = temp;
如果已知Rectangle temp; temp.X = 5;
有一个名为X
的公共整数字段,而Rectangle
是X
,则无需知道任何任何MyListOfRectangles
其他属性,构造函数等,以便知道上述代码将更改List<Rectangle>
但不会影响Rectangle
的任何其他属性,也不会影响MyListOfRectangles[5].X
的任何属性。很好,清晰,容易。与任何其他类型的数据类型不同,外露字段结构允许以清晰和一致的方式逐个编辑值。