如何将委托添加到接口C#


91

我班上需要一些代表。

我想使用该界面“提醒”我设置这些委托。

如何?

我的课看起来像这样:

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

Answers:


142

那些声明委托类型。它们不属于接口。使用这些委托类型的事件可以很好地出现在界面中:

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

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

该实现不会(也不应)重新声明委托类型,这要比重新声明接口中使用的任何其他类型多。


这对我不起作用。我很肯定我已经通过这种方式完成了所有工作,但是,我的界面中的处理程序并未得到认可。我实现该接口的类抱怨该类与System.EventHandler的接口返回类型不匹配。
Chucky

1
@Chucky:听起来您应该用简短但完整的示例来提出一个新问题,以演示该问题。我给出的答案确实有效。
乔恩·斯基特

4
我没有意识到委托与类具有相同的可访问性级别。我一直认为它们需要封装在一个类中。
Purusartha 2014年

7
@Purusartha:这不是可访问性-这只是一个代表是类型的物质(类,其实)一样多,接口等
乔恩斯基特

29

从.NET 3.5开始,您还可以使用System.Action委托,而无需声明自己的类型。

这将导致以下界面:

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

   event Action Started;
}

+1。我发现Action / Func比传统的委托类型更优雅(更易读)您可以在界面中定义它们。
chrnola 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 2010年

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

现在,事件args返回了您的类型,您可以将它们挂接到您定义的任何处理程序中。

供参考:https : //msdn.microsoft.com/zh-cn/library/edzehd2t(v=vs.110).aspx


0

在派生类中继承的接口将提醒您定义和链接在其中声明的内容。

但是您可能还想显式使用它,并且仍然需要将其与对象关联。

例如,使用控制反转模式:

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);
  }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.