Событие может появиться только в левой части += или -= dotnetstandard 2.1.
Я использую dot net standard 2.1 и С # 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);
}
}
но возьмите ошибку:
Ошибка Событие ICrawler.NextPage может появляться только слева от += или -=
Я продолжил это обучение, так в чем проблема?
1 ответ
Причина
Простое определение события, заканчивающееся на ;
в классе состоит из 2 частей: событие, которое содержит только средства доступа (методы) добавления / удаления, и делегат обработчика.
за
class Foo
{
public event EventHandler Bar;
}
равно
class Foo
{
//The event
public event EventHandler Bar
{
add => _bar += value;
remove => _bar -= value;
}
//The handler value
private EventHandler _bar;
}
Обратите внимание, что поле поддержки всегда private
, независимо от модификатора доступа в определении события. ТакBar?.Invoke()
фактически обращается к делегату обработчика напрямую, а не к средствам доступа, и может быть выполнено только внутри самого класса.
Но простое определение события, заканчивающееся на ;
в интерфейсе есть только абстрактное событие, которое содержит только абстрактные средства доступа добавления / удаления (абстрактные методы).
за
interface IFoo
{
event EventHandler Bar;
}
равно
interface IFoo
{
public abstract EventHandler Bar;
//The following syntax is invalid but shows how it works.
/*
event EventHandler Bar
{
abstract add;
abstract remove;
}
*/
}
Функция реализации интерфейса по умолчанию в 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; }
}
Чтобы событие могло быть вызвано где-то еще в реализации метода по умолчанию:
var handler = BarHandler;
handler?.Invoke(this, e);