修改成员时不调用C#对象设置器

时间:2013-02-18 23:38:22

标签: c# properties setter

我有以下包装类:

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;
    }
}

Property.Member中修改Foo()时,没有任何反应(跳过设置者)。但是,我仍然可以执行以下操作,例如:

    public void Foo()
    {
        Property = Property;
    }

并输入所需的setter。所以我的问题是,为什么不修改对象属性的成员调用该属性的setter?

4 个答案:

答案 0 :(得分:1)

因为您没有修改引用。您正在修改引用'member。

比方说,如果我站在房间的角落里说“抱这个苹果”。如果我进来并用香蕉切换苹果..我没有换过你,所以你很高兴。但如果我和其他人一起出门,你会抱怨我要替换你。

..无论如何,这是我的比喻。

此外,您已经使用I为类添加了前缀..这通常用于.NET域中的接口。

编辑:我意识到,如果我站在角落里拿着一块水果......当我替换你时,你可能不会抱怨..

答案 1 :(得分:1)

因为您没有设置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();
        }
    }
}

答案 2 :(得分:0)

在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。

答案 3 :(得分:0)

通常人们通过Add()方法直接将对象添加到列表中,而该方法又不会触发setter。

private List<string> _namesList = new List<string>();
// list of names
public List<string> NamesList
{    
    get
    {
    return _namesList;
    }
    set
    {
    if (value == _namesList)
    {
    return;
    }
    _namesList = value;
    }
}

在上面的NamesList属性中,如果你调用NamesList.Add(&#34; test&#34;),它就不会调用setter。简单的解决方案是将列表存储在一个新变量中,并逐渐将该变量设置为NamesList,例如

List<string> lst = new List<string>{ "test1" };
d.NamesList = lst;              // setter will fire.

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