繁体   English   中英

.NET-我应该直接调用事件吗?

[英].NET - Should I directly Invoke events?

我很久以来一直坚持使用模式,最近我意识到我忘记了为什么我习惯了这种方式。

public event EventHandler<string> SomethingChanged;
private void OnSomethingChanged(string something) => SomethingChanged?.Invoke(this, something);

因此,当我想调用事件时,我调用OnSomethingChanged(this, something); 为什么不做SomethingChanged?.Invoke(this, state); 直?

感觉很简单。 当时C#语法更复杂,但是今天基本上没有必要,这种OnSomethingChanged模式是否可以达到目的?

实际上,由于此模式很长,所以我总是只复制粘贴它并替换相关部分。 具有讽刺意味的是,我可以回想起几次复制粘贴导致调试我的软件时发现我在这里犯了一个错误,因为很着急。 这也使直接调用SomethingChanged更可取。

考虑以下示例:

public class BaseClass 
{
    private int id;
    public int Id 
    { 
        get { return id; }
        set { id = value; SomethingChanged(this, "id"); }
    }

    public event EventHandler<string> SomethingChanged;
}

public class DerivedClass : BaseClass
{
    private string name;
    public string Name 
    { 
        get { return name; }
        set 
        { 
            name = value; 
            //// cannot be invoked directly here
            // SomethingChanged(this, "name"); 
        }
    }
}

C#文档专门提到了这种情况

事件是一种特殊的委托类型,只能从声明它们的类中调用。 派生类不能直接调用在基类中声明的事件。 尽管有时您可能想要一个只能由基类引发的事件,但在大多数情况下,应启用派生类以调用基类事件。 为此,您可以在包装事件的基类中创建一个受保护的调用方法。 通过调用或重写此调用方法,派生类可以间接调用事件。

基类中触发事件的私有方法并没有太大帮助,应该对其进行protected 使该方法virtual以允许派生类在通知事件订阅者之前/之后添加一些功能也是明智的:

public class BaseClass 
{
    private int id;
    public int Id 
    { 
        get { return id; }
        set { id = value; OnSomethingChanged( "id"); }
    }

    public event EventHandler<string> SomethingChanged;

    protected virtual void OnSomethingChanged(string something)
    {
        SomethingChanged(this, something);
    }
}

public class DerivedClass : BaseClass
{
    private string name;
    public string Name 
    { 
        get { return name; }
        set 
        { 
            name = value; 
            OnSomethingChanged("name"); 
        }
    }

    protected override void OnSomethingChanged(string something)
    {
        base.OnSomethingChanged(something + " (event triggered from derived class)");
    }
}
public static void Main(string[] args)
{
    var item = new DerivedClass();
    item.SomethingChanged += (e,s) => Console.WriteLine(s);
    item.Id = 5;
    item.Name = "abc";
}

此修改后的示例显示:

id (event triggered from derived class)
name (event triggered from derived class)

暂无
暂无

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

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