修改成员时不调用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. 

但是直接将对象添加到列表/集合中是一个常见的错误。 🙂