2

通常、オブジェクトのプロパティセッターでは、次のようなPropertyChangedイベントを発生させることができます。

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void Notify(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public string UserNote
    {
        get { return _userNote; }
        set
        {
            _userNote = value;
            Notify("UserNote"); 
        }
    }

既存のコードベースでは、オブジェクトのすべてのプロパティが変更されたことを示すために、PropertyChangedEventArgsがnullで送信されているインスタンスが表示されます。これは非効率的であり、必要以上に多くのイベントがトリガーされることにつながるようです。また、オブジェクトが循環的に更新されるという問題も発生するようです。

これは今までに良い習慣ですか?

コード内のコメントはそれを正当化しようとします...

//The purpose of this method is to wire up clients of NotificationBase that are also
//NotificationBases to *their* clients. Consider the following classes:     
         public class ClassA : NotificationBase
         {
             public int Foo
             {
                 get { return 123; }
                 set { Notify("Foo"); }
             }
         }

         public class ClassB : NotificationBase
         {
             ClassA A = new ClassA();
             public ClassB()
             {
                 A.PropertyChanged += AllChanged;
             }
             public void SetFoo()
             {
                 A.Foo = 456;
             }
         }

         public class ClassC
         {
             ClassB B = new ClassB();
             public ClassC()
             {
                 B.PropertyChanged += delegate { dosomething(); };
                 B.SetFoo(); // causes "dosomething" above to be called
             }
         }

        /// ClassB.SetFoo calls ClassA.Foo's setter, which calls ClassA.Notify("Foo").
        /// The event registration in ClassB's ctor causes ClassB.AllChanged to be called, which calls
        /// ClassB.Notify(null) - implying that ALL of ClassB's properties have changed.
        /// The event registration in ClassC's ctor causes the "dosomething" delegate to be called.
        /// So a Notify in ClassA is routed to ClassC via ClassB's PropertyChanged event.

        protected void AllChanged(Object sender, PropertyChangedEventArgs e)
        {
            Notify(null);
        }

どんな考えでも大歓迎です。

よろしく、ファジー

4

3 に答える 3

3

これは、実際にはの設計(またはそのドキュメント)の問題ですPropertyChangedEventArgs。nullに設定PropertyNameすると、「このオブジェクトのすべてのプロパティが変更されました」という意味になります。ただし、クラスが封印されているか、リフレクションを使用していない限り、オブジェクトのすべてのプロパティが変更されたことを実際に知ることはできません。最も言えることは、オブジェクトの基本クラスのすべてのプロパティが変更されたことです。

これは、プロパティ変更通知を実装する封印されたクラスを作成する非常に少数のケースを除いて、私の本ではこの特定の規則を使用しないのに十分な理由です。

実際問題として、あなたが本当にやろうとしているのは、リスナーに「このオブジェクトの多くのプロパティが変更されたが、それらについて1つずつ説明するつもりはない」というイベントを1つ発生させることです。 「」あなたが言う時:

オブジェクトのすべてのプロパティが変更されたことを示すために、PropertyChangedEventArgsがnullで送信されているインスタンスが表示されます。これは非効率的であり、必要以上に多くのイベントがトリガーされることにつながるようです。

...実際の意図は正反対です。メソッドがオブジェクトの、、、、およびプロパティを変更し、オブジェクトFooに4つまたは5つのプロパティしかない場合、4つを上げるよりも1つのイベントを上げる方がおそらく良いでしょう。一方、オブジェクトに60個のプロパティがある場合、4つのイベントを発生させると、オブジェクトのすべてのリスナー(これらの4つのプロパティを確認していない場合でも)が、関心のあるプロパティが変更されたときに何でも実行できるようになります。 、それらのプロパティはそうではなかったからです。BarBazBat

問題は、設計されたプロパティ変更通知システムが、すべてのジョブに対して十分にきめ細かいツールではないことです。完全に汎用的に設計されており、組み込まれている特定のアプリケーションドメインに関する知識はありません。

そして、それは私には、あなたの設計に欠けているもの、つまりアプリケーションドメインの知識であるように思われます。

2番目の例では、Fixtureオブジェクトに(たとえば)の値に依存する10個のプロパティがある場合FixtureStatus、10個のプロパティ変更イベントを発生させるのは少し過剰に思えるかもしれません。多分そうです。たぶん、オブジェクトはFixtureStatusChanged代わりにイベントを発生させる必要があります。次に、アプリケーションドメインの知識を持つクラスは、この1つのイベントをリッスンし、イベントを無視できPropertyChangedます。(イベントが何を意味するのかわからないPropertyChangedオブジェクトが最新の状態を維持できるように、他のプロパティでイベントを発生させます。つまり、実装後にクラスで実装する必要がある場合です。)FixtureStatusChangedINotifyPropertyChangedFixtureStatusChanged

二次コメント:C#ユニバースのほとんどのクラスは、イベントを発生させるメソッドを実装している場合は、Fooそのメソッドを呼び出しますOnFoo。これは重要な規則です。メソッドとイベントの関係を明示的にし、メソッドを呼び出しているコードがイベントを発生させているという事実を認識しやすくします。 Notify一般的なメソッドの弱い名前です-誰に通知しますか?なにかの?-そしてこの場合、それは実際に明示的にされるべき何かを曖昧にします。プロパティ変更の通知は、命名規則が発生しているという事実を隠すことなく、十分に注意が必要です。

于 2010-08-12T19:08:53.277 に答える
0

他のものを無視すると、私はそれNotify(null)だけでは悪い習慣だと思います。それが何を意味するのかは本質的に明確ではなく、5年後にコードを作業する開発者にとっては、コメントに基づいて起こらない限り、おそらくそれは別の意味を持っていると思い込むでしょう。

于 2010-08-12T18:12:30.990 に答える
0

セッターを介して設定した他のプロパティの場合、計算されたプロパティ(セッターなし)がPropertyChangeNotificationを起動する必要がある状況に遭遇しました。

例えば

double Number {get {return num;} set { num = value; OnPropertyChanged( "Number"); OnPropertyChanged( "TwiceNumber"); }}

double TwiceNumber {get {return _num * 2.0;}}

原則として、私はプロパティのみを取得することでそれを行いますが、この場合、他のプロパティで変更通知を発行するプロパティが悪い理由はわかりません。しかし、他の場合にそれを行うと、私はおそらく自分が何をしているのかわからないと思います!

于 2010-08-12T18:16:39.077 に答える