Как добавить делегат в интерфейс С#

Мне нужно иметь некоторых делегатов в моем классе.

Я хотел бы использовать интерфейс, чтобы "напомнить" мне, чтобы установить эти делегаты.

Как?

Мой класс выглядит следующим образом:

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

Ответ 1

Объявляются типы делегатов. Они не принадлежат интерфейсу. События, использующие эти типы делегатов, могут быть в интерфейсе, хотя:

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

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

Реализация не будет (и не должна) переопределять тип делегирования, больше, чем он будет переопределять любой другой тип, используемый в интерфейсе.

Ответ 2

Начиная с .NET 3.5 вы также можете использовать делегаты System.Action без необходимости объявлять свой собственный тип.

Это приведет к следующему интерфейсу:

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

   event Action Started;
}

Ответ 3

Просто выделите делегат как свойство

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

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

Ответ 4

Ответ Джона Скита прав, я просто хочу добавить примечание.

Интерфейсов не существует, чтобы "напоминать" вам, что делать, или что включать в ваши классы. Интерфейсы - это средства абстракции, используемые в объектно-ориентированном программировании и методах проектирования. Возможно, вам вообще не требуется декларация интерфейса, если вы не хотите видеть некоторые конкретные экземпляры класса как интерфейс в другом месте вашей программы (абстракция).

Если вы хотите применить некоторые стандарты кодирования в своем проекте, вы можете попробовать использовать инструменты анализа кода (например, в Visual Studio). Они позволяют расширения, которые вы можете включить, чтобы добавить собственные правила анализа кода.

Используя анализ кода, если вы "забудете" добавить делегатов (хотя я не вижу смысла забывать об этом, как будто делегат не используется, он не нужен), вы получите предупреждение/ошибку.

Ответ 5

В одном из ваших комментариев указан обратный тип обработчика событий. Вас больше интересует тип обработчика или данные, возвращаемые из события? Если это последнее, то это может помочь. Если нет, то этого решения будет недостаточно, но может помочь вам приблизиться к тому, что вы ищете.

Все, что вам нужно сделать, - объявить обработчики событий как общие обработчики событий как в интерфейсе, так и в вашей реализации, и вы можете настроить результаты возврата.

Класс вашего класса будет выглядеть следующим образом:

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

Ответ 6

Интерфейс, унаследованный в вашем производном классе, напомнит вам определить и связать материал, который вы заявили в нем.

Но вы также можете использовать его явно, и вам все равно нужно связать его с объектом.

Например, с использованием инверсии шаблона управления:

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);
  }
}