arm*_*man 1 .net c#-8.0 .net-standard-2.1
我正在使用 dot net standard 2.1 和 c# 8,我想为我的类(接口)创建一个事件,我按照本教程 编写了一个接口:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
但请告诉我一个错误:
错误事件“ICrawler.NextPage”只能出现在+=或-=的左侧
我继续进行了这个训练,那么问题出在哪里呢?
以类结尾的简单事件定义;由两部分组成,即事件(仅包含添加/删除访问器(方法))和处理程序委托。
为了
class Foo
{
public event EventHandler Bar;
}
Run Code Online (Sandbox Code Playgroud)
等于
class Foo
{
//The event
public event EventHandler Bar
{
add => _bar += value;
remove => _bar -= value;
}
//The handler value
private EventHandler _bar;
}
Run Code Online (Sandbox Code Playgroud)
private请注意,无论事件定义的访问修饰符如何,支持字段始终为。因此Bar?.Invoke(),实际上是直接访问处理程序委托,而不是访问器,并且只能在类本身内完成。
但是以接口结尾的简单事件定义;只是抽象事件,它只包含添加/删除抽象访问器(抽象方法)。
为了
interface IFoo
{
event EventHandler Bar;
}
Run Code Online (Sandbox Code Playgroud)
等于
interface IFoo
{
public abstract EventHandler Bar;
//The following syntax is invalid but shows how it works.
/*
event EventHandler Bar
{
abstract add;
abstract remove;
}
*/
}
Run Code Online (Sandbox Code Playgroud)
C# 中的默认接口实现功能不会对其进行重大更改,因为接口不能包含任何字段(定义了 C# 中的接口是什么)。只要处理程序委托不存在,就不可能直接访问它,因此Bar?.Invoke()是无效的。
有一种解决方法是使用手动实现的事件(也是默认实现)和抽象属性作为处理程序委托:
interface IFoo
{
protected EventHandler BarHandler { get; set; }
event EventHandler Bar
{
add => BarHandler += value;
remove => BarHandler -= value;
}
}
class Foo : IFoo
{
EventHandler IFoo.BarHandler { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这样默认方法实现中的其他地方就可以调用该事件:
var handler = BarHandler;
handler?.Invoke(this, e);
Run Code Online (Sandbox Code Playgroud)