C# -事件-只能出现在+;=或-=

C# -事件-只能出现在+;=或-=,c#,event-handling,C#,Event Handling,我有一个循环中的事件。我试图防止同一方法被多次添加到事件中。我已经实现了add和remove访问器 但是,我得到一个错误,指出: ItemsProcessed只能出现在+=或-=的左侧 当我试着给他们打电话时,即使是在同一个班级里 ItemsProcessed(this, new EventArgs()); // Produces error public event EventHandler ItemsProcessed { add { ItemsProces

我有一个循环中的事件。我试图防止同一方法被多次添加到事件中。我已经实现了
add
remove
访问器

但是,我得到一个错误,指出:

ItemsProcessed只能出现在+=或-=的左侧

当我试着给他们打电话时,即使是在同一个班级里

ItemsProcessed(this, new EventArgs()); // Produces error

public event EventHandler ItemsProcessed
{
    add
    {
        ItemsProcessed -= value;
        ItemsProcessed += value;
    }
    remove
    {
        ItemsProcessed -= value;
    }
}

对于显式事件,您需要提供自己的后备存储—委托字段或类似于
EventHandlerList
的内容。当前代码是递归的。尝试:

private EventHandler itemsProcessed;
public event EventHandler ItemsProcessed
{
    add
    {
        itemsProcessed-= value;
        itemsProcessed+= value;
    }

    remove
    {
        itemsProcessed-= value;
    }
}
然后(请注意,我对“即将变成
null
”边缘案例重新线程化有点谨慎):

使用更新的C#版本,这可以简化:

itemsProcessed?.Invoke(this, EventArgs.Empty);

什么错误?我猜是它的堆栈溢出错误,因为您正在对自己的serlf(相同事件)调用add和remove。此外,您不能引发事件访问器

有效的方法是创建备份私有事件,该事件将被添加到或从公共访问器中删除,您应该引发此私有事件


Dang,晚了一分钟。

如果显式实现了
EventHandler
,则在触发事件时无法引用“属性”。您必须参考备份存储。

我无法从您的帖子中判断您是否试图从派生类引发事件,但我发现一件事是,您无法在基类中定义事件,然后(直接)在派生类中引发它,原因我还不清楚

因此,我在基类中定义了受保护的函数来引发事件(在这些基类中定义),如下所示:

// The signature for a handler of the ProgressStarted event.
// title: The title/label for a progress dialog/bar.
// total: The max progress value.
public delegate void ProgressStartedType(string title, int total);

// Raised when progress on a potentially long running process is started.
public event ProgressStartedType ProgressStarted;

// Used from derived classes to raise ProgressStarted.
protected void RaiseProgressStarted(string title, int total) {
    if (ProgressStarted != null) ProgressStarted(title, total);
}
然后在派生类中,我调用RaiseProgressStarted(title,total),而不是调用ProgressStarted(title,total)


这似乎是一个很长的路要走。也许其他人知道解决此问题的更好方法。

此外,您似乎通过访问
ItemsProcessed
函数本身中的
ItemsProcessed
创建了一个无限循环。作为参考,
EventName(args)
调用技巧仅适用于类似字段的事件,其中某些操作隐式解析为类中的字段(而不是事件)。我不得不说“一些”,因为确切的列表在C#3和C#4之间变化。不,他不知道堆栈溢出,因为他的代码甚至没有编译。是的,当Marc的答案发布后,我就不再考虑它了。。你是对的。一个缺点是:只能在类内访问为什么要访问类外的私有支持事件?子类化,duh。使内容受到保护。@nyrguds子类化很少有很好的理由访问支持字段;对于事件,更常见的方法是
protectedvirtual void OnItemsProcessed()=>itemsProcessed?.Invoke(这是EventArgs.Empty)-工作完成,无需公开对fieldWell的访问,我正在尝试创建一个自定义
OnMouseWheel
,它可以选择执行原始链接的
控件。MouseWheel
事件。。。我不能不禁用滚动。真令人沮丧。鼠标滚动是一种奇怪的半自动的东西。我刚刚意识到这是一篇5年前的文章。我遇到了这个问题,并弄明白了我到底在做什么,所以我发布了这个答案。也许这对某人会有帮助。呵呵,我刚刚又遇到了这个问题,不太记得是什么原因造成的,以及我是如何解决的,我从11个月前就找到了自己的答案。这很有趣。2019年,这解决了我的问题,感谢2015年关于2010年问题的帖子!:-我想这一定是事实,它解决了问题,但我真正想知道的是原因。也许在过去的几年里,有人已经明白了这一点?
// The signature for a handler of the ProgressStarted event.
// title: The title/label for a progress dialog/bar.
// total: The max progress value.
public delegate void ProgressStartedType(string title, int total);

// Raised when progress on a potentially long running process is started.
public event ProgressStartedType ProgressStarted;

// Used from derived classes to raise ProgressStarted.
protected void RaiseProgressStarted(string title, int total) {
    if (ProgressStarted != null) ProgressStarted(title, total);
}