0

我有以下包装类:

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

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

4

4 回答 4

3

因为您没有修改参考。您正在修改引用的成员。

例如,假设我站在房间的角落说“拿着这个苹果”。如果我进来用香蕉换苹果..我没有换你,所以你很高兴。但如果我把你换成别人,你会抱怨我要代替你。

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

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

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

于 2013-02-18T23:42:55.450 回答
1

因为您没有设置Property. 您的代码只是调用 的 getter Property,然后设置Member字段的值(如果它是一个属性,它将调用 setter,Member这里不是这种情况)。

如果要在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();
        }
    }
}
于 2013-02-18T23:43:47.133 回答
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

于 2013-02-18T23:46:50.190 回答
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("test") 它不会调用 setter。简单的解决方案是将列表存储在一个新变量中并逐渐将该变量设置为 NamesList 例如

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

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

于 2018-02-22T07:32:05.537 回答