简体   繁体   English

C#CS0079事件处理编译错误

[英]C# CS0079 Event Handling Compile Errors

I can't compile the following code. 我无法编译以下代码。

Compile error CS0079 : The event 'CustomEvent' can only appear on the left hand side of += or -= 编译错误CS0079:事件'CustomEvent'只能出现在+ =或 - =的左侧

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

How can I make this work? 我怎样才能做到这一点?

My implementation is like this: 我的实现是这样的:

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
}

Your edit shows a recursive call: you are declaring a custom event, which means you are meant to provide a backing field; 您的编辑显示递归调用:您正在声明自定义事件,这意味着要提供支持字段; for example: 例如:

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

Note that in Func I am referring to the field ( customEvent ), not the event ( CustomEvent ). 请注意,在Func我指的是字段customEvent ),而不是事件CustomEvent )。

However, this is simpler are better (thread-safe) as a field-like event: 但是,这更简单(线程安全)作为类似字段的事件:

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

A field-like event uses the event keyword, but omits the accessors: the compiler adds a lot of boilerplate for you (a backing field, and thread-safe add/remove implementations). 类似字段的事件使用event关键字,但省略了访问器:编译器为您添加了许多样板(支持字段和线程安全的添加/删除实现)。 Further, it allows access to the backing filed via the event name (from the declaring type), hence how the line var tmp = CustomEvent; 此外,它允许通过事件名称 (来自声明类型)访问后备文件,因此行var tmp = CustomEvent; works. 作品。

Also: be very careful with static events; 另外:对静态事件要非常小心; they are a great way to accidentally keep lots of objects alive. 它们是意外保持大量物体存活的好方法。

You can only test/invoke an event if it is a field-like event declared in the current type. 如果事件是在当前类型中声明的类字段事件,则只能测试/调用事件 So: there are two scenarios that would cause this: 所以:有两种情况会导致这种情况:

  1. it isn't a field-like event, but has custom add / remove accessors: in which case, only your custom code knows how the delegate is stored 它不是类似字段的事件,但具有自定义add / remove访问器:在这种情况下,只有您的自定义代码知道如何存储代理

  2. it isn't declared in the current type, but is in a base-type or some unrelated object: in which case, you'll need to get the declaring type to invoke the event, usually via an OnCustomEvent method. 它不是在当前类型中声明,而是在基类型或某个不相关的对象中:在这种情况下,您需要通过OnCustomEvent方法获取声明类型来调用事件。 In the case of a base-type, the convention would be to make this method protected virtual , which allows sub-classes to invoke the event and hook into the event via override 在基类型的情况下,惯例是使该方法protected virtual ,这允许子类调用事件通过override挂钩到事件中


(comments) (评论)

It looks like the case1. 它看起来像case1。 however, I don't understand what to do to resolve this issue. 但是,我不明白如何解决这个问题。

If you have custom add / remove , then how to invoke it is implementation-specific (I could tell you more if I could see the add / remove ), but let's look at two common implementations: 如果你有自定义add / remove ,那么如何调用它是特定于实现的(如果我能看到add / remove ,我可以告诉你更多),但让我们看看两个常见的实现:

1a: a backing delegate: 1a:支持代表:

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

in this case, the "invoke" implementation would be simply: 在这种情况下,“调用”实现将简单地:

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

or if you are feeling extra-cautious: 或者如果你感到非常谨慎:

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

1b: an EventHandlerList (used for sparse events): 1b: EventHandlerList (用于稀疏事件):

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

in which case the invoke implementation would be: 在这种情况下,调用实现将是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM