18

「RaisePropertyChanged」のようなメソッドを回避するためにクラスをコーディングしようとしました。その実装を持つクラスから継承できることは知っていますが、場合によっては継承できません。拡張メソッドを試しましたが、VisualStudioに文句があります。

public static class Extension
{
    public static void RaisePropertyChanged(this INotifyPropertyChanged predicate, string propertyName)
    {
        if (predicate.PropertyChanged != null)
        {
            predicate.PropertyChanged(propertyName, new PropertyChangedEventArgs(propertyName));
        }
    }
}

と言いました:

「イベント' System.ComponentModel.INotifyPropertyChanged.PropertyChanged'は、+=または-=の左側にのみ表示されます。」

4

4 に答える 4

20

リードは正しいです。しかし、私はあなたが何をしようとしているのかわかります(コードを再利用可能にします— <strong>あなたにとって良いことです)。PropertyChangedEventHandler そして、これは、デリゲートINotifyPropertyChanged自体を受け入れ、実装内から渡すことで簡単に修正できることが多いことを指摘しておきます。

public static void Raise(this PropertyChangedEventHandler handler, object sender, string propertyName)
{
    if (handler != null)
    {
        handler(sender, new PropertyChangedEventArgs(propertyName));
    }
}

次に、を実装するクラス内からINotifyPropertyChanged、次のようにこの拡張メソッドを呼び出すことができます。

PropertyChanged.Raise(this, "MyProperty");

これが機能するのは、Marcが言ったように、イベントを宣言するクラス内で、フィールドのようにアクセスできるためです(つまり、拡張メソッドを含むメソッドへのデリゲート引数として渡すことができます)。

于 2011-02-07T18:48:25.493 に答える
11

イベントを発生させることができるのは、それが定義されているクラス内からのみです。

この行:

predicate.PropertyChanged(propertyName, new PropertyChangedEventArgs(propertyName));

predicateこの拡張メソッドを定義するクラスではないため、失敗します。

これが、Extensionメソッドを使用するのではなく、通常、基本クラスを介して処理される理由の1つです。

于 2011-02-07T18:45:43.507 に答える
4

イベントは、実際には追加/削除を伴う単なるAPIです(技術的に、CLIで使用可能なオプションの「呼び出し」がありますが、c#コンパイラはそれを提供しません)。

あなたが持っているのは、フィールドのようなイベントです。フィールドのようなイベントは、宣言型の外部から追加/削除APIとして機能し、宣言型の内部でのみフィールドのように機能し、デリゲートとして扱う必要がある場合にのみ機能します-最も一般的には、サブスクライバーを呼び出します(これはここでのc#4の微妙な変更。c#4の前では、タイプ内からのすべてのアクセスは、+ = /-=を含め、フィールドに対して機能します。

定義上、拡張メソッドを宣言型の内部に含めることはできません。拡張メソッドを提供できるのは、最上位の(ネストされていない)静的クラスのみです。したがって、拡張メソッドがフィールドのようなイベントを直接呼び出すことはできません。

于 2011-02-07T18:49:06.227 に答える
2

キーワードを使用してイベントを定義するとevent、C#コンパイラは実際に舞台裏で多くのことを生成します。

event EventHandler MyEvent;

次のようなものに変換されます(実際にはいくつかのロックやその他のチェックが追加されるわけではありませんが)...

private EventHandler _myEvent;

public EventHandler MyEvent
{
  add( EventHandler handler )
  { 
    _myEvent += handler;
  }
  remove( EventHandler handler )
  {
    _myEvent -= handler;
  }
}

ご覧のとおり、実際のEventHandler_myEventはプライベートであり、直接呼び出すことはできません。

于 2011-02-07T18:49:44.927 に答える