The event can only appear on the left hand side of += or -= dotnetstandard 2.1 [duplicate]

牧云@^-^@ 提交于 2020-06-29 05:45:07

问题


I'm using dot net standard 2.1 and c# 8, I want to create an event for my class (interface), I follow this tutorial and I wrote an interface:

using System;
using Crawler.Paging;

namespace Crawler
{
    public interface ICrawler
    {
        public event EventHandler NextPage;
        protected virtual void OnNextPage(EventArgs e)
        {

            EventHandler handler = NextPage;
            handler?.Invoke(this,e);
        }
        void Paging(IPaging paging);
    }
}

but take me an error:

Error The event 'ICrawler.NextPage' can only appear on the left hand side of += or -=

I proceeded with this training, so where is the problem?


回答1:


Reason

A simple event definition ending with ; in a class is made of 2 parts, which are the event, which only contains both add/remove accessors (methods), and the handler delegate.

for

class Foo
{
    public event EventHandler Bar;
}

equals to

class Foo
{
    //The event
    public event EventHandler Bar
    {
        add => _bar += value;
        remove => _bar -= value;
    }

    //The handler value
    private EventHandler _bar;
}

Note that the backing field is always private, regardless of the access modifier of the event definition. So Bar?.Invoke() is actually accessing the handler delegate directly, not the accessors, and can only be done within the class itself.

But a simple event definition ending with ; in an interface is only the abstract event, which only contains both add/remove abstract accessors (abstract methods).

for

interface IFoo
{
    event EventHandler Bar;
}

equals to

interface IFoo
{
    public abstract EventHandler Bar;
    //The following syntax is invalid but shows how it works.
    /*
    event EventHandler Bar
    {
        abstract add;
        abstract remove;
    }
    */
}

The default interface implementation feature in C# does not breaking-change it, for an interface cannot contain any field (which defines what interface in C# is). As long as the handler delegate does not exist, it is not possible to access it directly, therefore Bar?.Invoke() is invalid.

Solution

There is a workaround by using a manually implemented event (which is also a default implementation) with an abstract property as the handler delegate:

interface IFoo
{
    protected EventHandler BarHandler { get; set; }

    event EventHandler Bar
    {
        add => BarHandler += value;
        remove => BarHandler -= value;
    }
}

class Foo : IFoo
{
    EventHandler IFoo.BarHandler { get; set; }
}

So that somewhere else in a default method implementation could invoke the event:

var handler = BarHandler;
handler?.Invoke(this, e);


来源:https://stackoverflow.com/questions/61558648/the-event-can-only-appear-on-the-left-hand-side-of-or-dotnetstandard-2-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!