web-dev-qa-db-ja.com

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

クラスにデリゲートが必要です。

インターフェイスを使用して、これらのデリゲートを設定することを「思い出させ」たいです。

方法?

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

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
{
   // ?????
}
77
Asaf

これらはデリゲートを宣言していますtypes。インターフェイスに属していません。ただし、イベントsingこれらのデリゲートタイプは、インターフェイスに存在しても問題ありません。

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

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

実装は、インターフェイスで使用される他の型を再宣言する場合と同じように、デリゲート型を再宣言しません(また、すべきではありません)。

127
Jon Skeet

.NET 3.5以降では、System.Actionデリゲートを使用することもできます。これにより、次のインターフェイスが作成されます。

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

   public event Action Started;
}
27
DELUXEnized

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

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

プロジェクトにいくつかのコーディング標準を適用したい場合は、コード分析ツール(Visual Studioなど)を使用してみてください。拡張機能を使用でき、独自のコード分析ルールを追加するために組み込むことができます。

コード分​​析を使用して、デリゲートを追加するのを「忘れる」と(デリゲートが使用されていないかのように忘れるポイントはありませんが、必要ありません)、警告/エラーが表示されます。

7
Iravanchi

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

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

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

コメントの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

1
Reuben Soto

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

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

たとえば、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);
  }
}
0
Latency