C#8默认接口实现/特性的事件继承 [英] Event Inheritance with C#8 Default Interface Implementation/Traits

查看:193
本文介绍了C#8默认接口实现/特性的事件继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前很少有文档说明新的C#8默认接口实现(特征)的事件限制.我尤其对发行说明对于C#8 ,请不要提及接口特征的事件.当我继续尝试寻找答案时,我也无法从问题列表.

There is currently little documentation surrounding the limitations of events with the new C#8 default interface implementations (traits). I am particularly confused with the spec proposal. Not only is the example given invalid C# (the "override" event is missing an identifier), but implementing any of these in C#8 (VS2019, .NET Core 3.0) returns a host of compiler exceptions. In addition, the release notes for C#8 don't make any mention of events for interface traits. As I continued to try and track down an answer, I also couldn't gather anything useful from the open issues list.

问题是:此功能是否已实现且可用?如果是这样,正确的语法是什么?

So the questions are: is this feature implemented and usable? If so, what is the proper syntax?

推荐答案

默认接口成员用于特征,而不仅仅是版本控制,并且INPC特征是有意义的.

Default interface members are used for traits, not just versioning, and an INPC trait would make sense.

不幸的是,现在无法使用DIM引发事件,并且无法实现似乎无法会很痛苦-这将需要彻底改变事件机制并破坏大量代码,尤其是库代码.我们可以使用DIM添加或删除处理程序,但这并不是那么有用.

Unfortunately, it's not possible to use DIMs to raise events right now, and implementing this seems to be a pain - it would require overhauling the events mechanism and break a ton of code, especially library code. We can use DIMs to add or remove handlers, but that's not so useful.

有类似这样的东西会很好:

It would be nice to have something like :

interface InpcTrait : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private T Set(T value,String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        return value;
    }
}

class Customer
{
    private string _name;
    public string Name 
    {
        get=>_name;
        set=>_name=Set(value,"Name");
    }
}


不幸的是,这是不可能的.这是因为类中的event关键字会生成一个后备字段,其中包含事件处理程序和添加/删除访问器.引发事件时,我们将其称为事件处理程序.

Unfortunately, this isn't possible. That's because the event keyword in a class generates a backing field that holds the event handler and add/remove accessors. When we raise the event, we call that event handler.

接口不能具有状态,这意味着我们无法访问该事件以引发它.

Interfaces can't have state, which means we can't access that event to raise it.

当我们在接口中指定事件时,我们将创建一个虚拟事件,并且编译器仅允许向其添加/删除事件处理程序.提升接口仍然需要访问后备字段.

When we specify an event in an interface, we create a virtual event and the compiler only allows adding/removing event handlers to it. Raising the interface still requires access to the backing field.

这Sharplab.io示例表明:

public class DemoCustomer : INotifyPropertyChanged
{
    // These fields hold the values for the public properties.
    private Guid idValue = Guid.NewGuid();
    private string customerNameValue = String.Empty;
    private string phoneNumberValue = String.Empty;

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

生成

    [CompilerGenerated]
    private PropertyChangedEventHandler m_PropertyChanged;

    public event PropertyChangedEventHandler PropertyChanged
    {
        [CompilerGenerated]
        add
        {
            //some code
        }
        [CompilerGenerated]
        remove
        {
            //some code
        }
    }

    private void NotifyPropertyChanged(string propertyName = "")
    {
        if (this.m_PropertyChanged != null)
        {
            this.m_PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

我们可以做的是添加或删除事件处理程序,但是我们甚至无法检查事件是否已经具有其他处理程序.我们可能会多次添加相同的事件处理程序.

What we can do, is add or remove event handlers, but we can't even check whether the event already has other handlers. We risk adding the same event handler multiple times.

这是有效的:

interface INPCtrait:System.ComponentModel.INotifyPropertyChanged
{            
    private  void AddSomeDefaultHandler()
    {
       PropertyChanged+=Something;
    }

    private  void RemoveDefaultHandler()
    {
       PropertyChanged-=Something;
    }

    public void Something(Object sender,System.ComponentModel.PropertyChangedEventArgs args)
    {
    }    
}

但是我们无法知道是否需要添加该默认处理程序.

But we have no way of knowing whether we need to add that default handler or not.

这篇关于C#8默认接口实现/特性的事件继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆