修改成员时不调用C#对象设置器
我有以下包装类:
public class Wrapper { public int Member; }
在另一个课程中,我有以下内容:
public class ContainerClass { private Wrapper data; public Wrapper Property { get { return data; } set { data = value; } } public void Foo() { Property.Member = 42; } }
在Foo()
修改Property.Member
,没有任何反应(跳过setter)。 但是,我仍然可以执行以下操作,例如:
public void Foo() { Property = Property; }
并输入所需的setter。 所以我的问题是,为什么不修改对象属性的成员调用该属性的setter?
因为您没有设置Property
的值。 您的代码只调用Property
的getter,然后设置Member
字段的值(如果它是属性,则会调用Member
的setter,这不是这里的情况)。
如果要在设置Member
时执行代码,则需要执行
public class Wrapper { private int member; public int Member { get { return this.member; } set { this.member = value; DoSomething(); } } }
或者更优雅的解决方案是使用事件。 内置的INotifyProperyChanged界面为您提供了一个非常好的模板。
using System.ComponentModel; public class Wrapper : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private int member; public int Member { get { return this.member; } set { this.member = value; this.OnPropertyChanged("Member"); } } protected void OnPropertyChanged(string name) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } } public class ContainerClass { private Wrapper data; public Wrapper Property { get { return data; } set { data = value; } } public void Foo() { data.PropertyChanged += data_PropertyChanged; Property.Member = 42; } private void data_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Member") { DoStuff(); } } }
因为您没有修改引用。 您正在修改引用’成员。
比方说,如果我站在房间的角落说“抱这个苹果”。 如果我进来并用香蕉切换苹果..我没有换过你,所以你很高兴。 但如果我和其他人一起出门,你会抱怨我正在替换你。
..无论如何,这是我的比喻。
此外,您已经为我添加了一个类…这通常用于.NET域中的接口。
编辑:我意识到,如果我站在角落里拿着一块水果……当我替换你时你可能不会抱怨..
在foo的构造函数中,您正在设置类Wrapper的字段。
public void Foo() { Property.Member = 42; // No property set, you are accessing a field. }
在第二个示例中,您要设置属性
public void Foo() { // Setting Property "Property" to the value of "Property" // You should see both the getter and the setter called. Property = Property; }
我不知道你想要做什么,但也许你想让Wrapper拥有一个属性。
public class Wrapper { private int member; public int Member { get { return data; } set { data = value; } } }
然后当你做Property.Member = 42时,将在Wrapper.Member上调用setter
通常人们通过Add()方法直接将对象添加到列表中,而该方法又不会触发setter。
private List _namesList = new List (); // list of names public List NamesList { get { return _namesList; } set { if (value == _namesList) { return; } _namesList = value; } }
在上面的NamesList属性中,如果调用NamesList.Add(“test”),它将不会调用setter。 简单的解决方案是将列表存储在新变量中,并逐渐将该变量设置为NamesList,例如
List lst = new List { "test1" }; d.NamesList = lst; // setter will fire.
但是直接将对象添加到列表/集合中是一个常见的错误。 🙂