デリゲートをインターフェイスに追加する方法C#


89

クラスに何人かの代表者が必要です。

インターフェイスを使用して、これらのデリゲートを設定するように「通知」します。

方法?

私のクラスは次のようになります:

public class ClsPictures : myInterface
{
    // Implementing the IProcess interface
    public event UpdateStatusEventHandler UpdateStatusText;
    public delegate void UpdateStatusEventHandler(string Status);

    public event StartedEventHandler Started;
    public delegate void StartedEventHandler();
}

これらのデリゲートを強制するインターフェイスが必要です。

public interface myInterface
{
   // ?????
}

回答:


140

それらはデリゲートを宣言しています。それらはインターフェースに属していません。ただし、これらのデリゲートタイプを使用するイベントは、インターフェースに含めても問題ありません。

public delegate void UpdateStatusEventHandler(string status);
public delegate void StartedEventHandler();

public interface IMyInterface
{       
    event UpdateStatusEventHandler StatusUpdated;    
    event StartedEventHandler Started;
}

実装では、デリゲート型を再宣言しないでください(再宣言しないでください)。これは、インターフェイスで使用される他の型を再宣言する場合と同じです。


これは私にとってはうまくいきません。私はすべてをこの方法で実行したことを確信していますが、インターフェイス内のハンドラーが認識されていません。インターフェイスを実装する私のクラスは、クラスがSystem.EventHandlerのインターフェイスの戻り値の型と一致しないと不平を言っています。
チャッキー2013

1
@Chucky:問題をデモする短い完全な例で新しい質問をする必要があるようです。私が与えた答えは本当にうまくいきます。
ジョンスキート2013

4
デリゲートがクラスと同じレベルのアクセシビリティを持っていることを知りませんでした。クラスにカプセル化する必要があるといつも思っていました。
Purusartha 2014年

7
@プルサルタ:それはアクセシビリティではありません-それは、デリゲートが型(実際にはクラス)であり、インターフェイスなどと同じくらいの問題です
Jon Skeet

29

.NET 3.5以降では、独自の型を宣言する必要なく、System.Actionデリゲートを使用することもできます。

これにより、次のインターフェイスが生成されます。

public interface myInterface
{       
   // Implementing the IProcess interface
   event Action<String> UpdateStatusText;

   event Action Started;
}

+1。私はアクション/ funcは、伝統的なデリゲート型よりはるかにエレガント(と読める)であることを見つける、あなたのインターフェイスでそれらを定義することができます。
クロノラ2014

2
この回答は質問(myInterfaceの実装方法)には対応していません。
lharper71

10

デリゲートをプロパティとして公開するだけです

public delegate void UpdateStatusEventHandler(string status);
public delegate void StartedEventHandler();

public interface IMyInterface
{       
    UpdateStatusEventHandler StatusUpdated {get; set;}    
    StartedEventHandler Started {get; set;}
}

7

Jon Skeetの答えは正しいです。メモを追加したいだけです。

インターフェイスは、何をすべきか、またはクラスに何を含めるかを「思い出させる」ためにありません。インターフェイスは抽象化の手段であり、オブジェクト指向プログラミングおよび設計メソッドで使用されます。プログラムの他の場所でインターフェイスとしていくつかの具象クラスインスタンスを見たい場合を除いて、インターフェイス宣言はまったく必要ないかもしれません(抽象化)。

プロジェクトにコーディング標準を適用したい場合は、(Visual Studioのような)コード分析ツールを使用することをお勧めします。これにより、独自のコード分析ルールを追加するために組み込むことができる拡張が可能になります。

コード分​​析を使用して、デリゲートを追加するのを「忘れた」場合(デリゲートが使用されていないかのように、それを忘れる意味はわかりませんが)、警告/エラーが発生します。


1
あなたは正しいかもしれませんが、良いドキュメンテーションがあってもしばらくすると思い出すことが難しいといういくつかの仮定をするときがあります。私は自分のコードを再利用しようとしますが、中核とそうでないものを思い出せないことがあります(デリゲートに関しては
Asaf

1

コメントの1つが戻り値のタイプのイベントハンドラーを参照しています。ハンドラーのタイプ、またはイベントから返されるデータに関心がありますか?後者の場合、これが役立つことがあります。そうでない場合、このソリューションでは十分ではありませんが、探しているものに近づけるのに役立つ場合があります。

必要なのは、インターフェイスと実装の両方でイベントハンドラーを汎用イベントハンドラーとして宣言することだけで、返される結果をカスタマイズできます。

コンクリートクラスは次のようになります。

public class ClsPictures : myInterface
{
    // Implementing the IProcess interface
    public event EventHandler<UpdateStatusEventArgs> UpdateStatusText;
    //no need for this anymore: public delegate void UpdateStatusEventHandler(string Status);

    public event EventHandler<StartedEventArgs> Started;
    //no need for this anymore: public delegate void StartedEventHandler();
}

インターフェイスは次のようになります。

public interface myInterface
{
   event EventHandler<StartedEventArgs> Started;
   event EventHandler<UpdateStatusEventArgs> UpdateStatusText;
}

これで、イベント引数が型を返すようになったので、定義した任意のハンドラーでそれらをフックできます。

参照:https : //msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx


0

派生クラス内で継承されたインターフェースは、宣言したものを定義してリンクすることを思い出させます。

ただし、明示的に使用することもできますが、それでもオブジェクトに関連付ける必要があります。

たとえば、Inversion of Controlパターンを使用します。

class Form1 : Form, IForm {
   public Form1() {
     Controls.Add(new Foo(this));
   }

   // Required to be defined here.
   void IForm.Button_OnClick(object sender, EventArgs e) {
     ...
     // Cast qualifier expression to 'IForm' assuming you added a property for StatusBar.
     //((IForm) this).StatusBar.Text = $"Button clicked: ({e.RowIndex}, {e.SubItem}, {e.Model})";
   }
 }

このようなものを試すことができます。

interface IForm {
  void Button_OnClick(object sender, EventArgs e);
}


class Foo : UserControl {
  private Button btn = new Button();

  public Foo(IForm ctx) {
     btn.Name = "MyButton";
     btn.ButtonClick += ctx.Button_OnClick;
     Controls.Add(btn);
  }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.