【问题标题】:C# CS0079 Event Handling Compile ErrorsC# CS0079 事件处理编译错误
【发布时间】:2012-12-21 07:17:02
【问题描述】:

我无法编译以下代码。

编译错误 CS0079:事件“CustomEvent”只能出现在 += 或 -= 的左侧

if (CustomEvent != null)   //CS0079
    CustomEvent(null, null);  //CS0079

我怎样才能做到这一点?

我的实现是这样的:

public delegate void EventHandler(object sender, EventArgs e);  
public static event EventHandler CustomEvent
{
    add    { CustomEvent += value; }
    remove { CustomEvent -= value; }
 }
private static void Func()
{
    if (CustomEvent != null)      //CS0079
        CustomEvent(null, null);  //CS0079
}

【问题讨论】:

  • 您试图将控件与您自己的自定义事件联系起来吗?
  • @SpaceApple 他不是:他在调用
  • 编辑清楚地表明:我将添加另一个答案...

标签: c# .net events compiler-errors


【解决方案1】:

您的编辑显示了一个递归调用:您正在声明一个自定义事件,这意味着 旨在提供一个支持字段;例如:

private static EventHandler customEvent;
public static event EventHandler CustomEvent
{
    add    { customEvent += value; }
    remove { customEvent -= value; }
 }
private static void Func()
{
    var tmp = customEvent;
    if (tmp != null) tmp(null, null);
}

请注意,在Func 中,我指的是字段 (customEvent),而不是事件强> (CustomEvent)。

但是,作为类字段事件,这更简单更好(线程安全):

public static event EventHandler CustomEvent;
private static void Func()
{
    var tmp = CustomEvent;
    if (tmp != null) tmp(null, null);
}

类似字段的事件使用event 关键字,但省略访问器:编译器为您添加了许多样板文件(支持字段和线程安全的添加/删除实现) .此外,它允许通过事件名称(从声明类型)访问支持文件,因此var tmp = CustomEvent; 行的工作原理。

另外:对静态事件要非常小心;它们是意外保持大量对象存活的好方法。

【讨论】:

  • 谢谢马克!我猜这个gavaghan.org/blog/2007/07/25/… 声明“当您声明一个事件时,编译器会为您提供一个隐藏的 MulticastDelegate 字段,该字段管理事件侦听器的集合。实现 += 和 -= 运算符以从隐藏的委托中添加和删除处理程序.但是,您可以分别使用关键字 add 和 remove 为 += 和 -= 显式实现自己的行为"
  • @Chris 该描述不适用于“类字段事件”,即您省略了 add/remove 访问器。如果您提供访问器,您将完全控制实现。有点像自动实现的属性与常规属性。我已发表评论以更正该博客文章:)
【解决方案2】:

您只能测试/调用一个事件,如果它是在当前类型中声明的类字段事件。所以:有两种情况会导致这种情况:

  1. 它不是类似字段的事件,但有自定义的add/remove 访问器:在这种情况下,只有您的自定义代码知道委托的存储方式

  2. 它没有在当前类型中声明,而是在基类型或一些不相关的对象中:在这种情况下,您需要获取声明类型来调用事件,通常通过 @ 987654323@ 方法。在基类型的情况下,约定是将此方法设为protected virtual,它允许子类调用事件通过override挂钩到事件中


(cmets)

看起来像 case1。但是,我不明白如何解决这个问题。

如果你有自定义的add/remove,那么如何调用它是特定于实现的(如果我能看到add/remove,我可以告诉你更多信息),但让我们看看两个常见的实现:

1a:支持代表:

private EventHandler someEvent;
public event EventHandler SomeEvent
{
    add { someEvent += value; }
    remove { someEvent -= value; }
}

在这种情况下,“调用”实现很简单:

if(someEvent != null) someEvent(this, EventArgs.Empty);

或者如果您感到格外小心:

var handler = someEvent;
if(handler != null) handler(this, EventArgs.Empty);

1b:EventHandlerList(用于稀疏事件):

private static readonly object SomeEventKey = new object();
public event EventHandler SomeEvent
{
    add { Events.AddHandler(SomeEventKey, value); }
    remove { Events.RemoveHandler(SomeEventKey, value); }
}

在这种情况下,调用实现将是:

var handler = (EventHandler)Events[SomeEventKey];
if(handler != null) handler(this, EventArgs.Empty);

【讨论】:

  • 看起来像case1。但是,我不明白如何解决这个问题。
  • @Chris 我将在 1 上进行扩展,然后...给我一分钟
  • 由于 if(customEvent!=null) 在另一个函数中使用,此表达式本身会导致编译错误 CS0079。这就是问题所在。
猜你喜欢
  • 2013-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多