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

2番目の例では、プロパティを設定しています

public void Foo()
{
    // Setting Property "Property" to the value of "Property"
    // You should see both the getter and the setter called.
    Property = Property; 
}

あなたが何をしようとしているのかわかりませんが、おそらくあなたはラッパーにもプロパティを持たせたいと思っていました。

public class Wrapper
{
private int member;
public int Member
{
    get { return data; }
    set { data = value; }
}
}

次に、Property.Member = 42を実行すると、SetterがWrapper.Memberで呼び出されます。

于 2013-02-18T23:46:50.190 に答える
0

通常、人々はAdd()メソッドによってオブジェクトをリストに直接追加しますが、これはセッターをトリガーしません。

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 に答える