简体   繁体   English

C#语言设计:事件的显式接口实现

[英]C# Language Design: explicit interface implementation of an event

Small question about C# language design :)) 关于C#语言设计的小问题:))

If I had an interface like this: 如果我有这样的界面:

interface IFoo {
  int Value { get; set; }
}

It's possible to explicitly implement such interface using C# 3.0 auto-implemented properties: 可以使用C#3.0自动实现的属性显式实现此类接口:

sealed class Foo : IFoo {
  int IFoo.Value { get; set; }
}

But if I had an event in the interface: 但如果我在界面中有一个事件:

interface IFoo {
  event EventHandler Event;
}

And trying to explicitly implement it using field-like event: 并尝试使用类似字段的事件显式实现它:

sealed class Foo : IFoo {
  event EventHandler IFoo.Event;
}

I will get the following compiler error: 我将得到以下编译器错误:

error CS0071: An explicit interface implementation of an event must use event accessor syntax

I think that field-like events is the some kind of dualism for auto-implemented properties. 我认为类似字段的事件是自动实现属性的某种二元论。

So my question is: what is the design reason for such restriction done? 所以我的问题是: 这种限制的设计原因是什么?

Interesting question. 有趣的问题。 I did some poking around the language notes archive and I discovered that this decision was made on the 13th of October, 1999, but the notes do not give a justification for the decision. 我做了一些关于语言笔记档案的讨论,我发现这个决定是在1999年10月13日作出的,但是这些笔记没有给出决定的理由。

Off the top of my head I don't see any theoretical or practical reason why we could not have field-like explicitly implemented events. 在我的头脑中,我没有看到任何理论或实际原因,为什么我们不能有类似字段显式实现的事件。 Nor do I see any reason why we particularly need to. 我也没有看到任何我们特别需要的理由。 This may have to remain one of the mysteries of the unknown. 这可能不得不是未知的奥秘之一。

I guess it might have to do with the fact that you can't call an explicit interface implementation from other members of the class: 我想这可能与你不能从类的其他成员调用显式接口实现这一事实有关:

public interface I
{
    void DoIt();
}

public class C : I
{
    public C()
    {
        DoIt(); // error CS0103: The name 'DoIt' does not exist in the current context
    }

    void I.DoIt() { }
}

Note that you can call the method by upcasting to the interface first: ((I)this).DoIt(); 请注意,您可以先通过向上转换到接口来调用该方法: ((I)this).DoIt(); . A bit ugly but it works. 有点难看,但它的工作原理。

If events could be explicitly implemented as ControlFlow (the OP) suggested, then how would you actually raise them? 如果事件可以显示为ControlFlow(OP)建议,那么你将如何实际提出它们? Consider: 考虑:

public interface I
{
    event EventHandler SomethingHappened;
}

public class C : I
{
    public void OnSomethingHappened()
    {
        // Same problem as above
        SomethingHappened(this, EventArgs.Empty);
    }

    event EventHandler I.SomethingHappened;
}

Here you cannot even raise the event by upcasting to the interface first, because events can only be raised from within the implementing class. 在这里,您甚至无法通过向上转换到接口来引发事件,因为事件只能从实现类中引发。 It therefore seems to make perfect sense to require accessor syntax for explicitly implemented events. 因此,对于明确实现的事件要求访问器语法似乎是完全合理的。

When explicitly implementing an event that was declared in an interface, you must use manually provide the add and remove event accessors that are typically provided by the compiler. 显式实现在接口中声明的事件时,必须使用手动提供通常由编译器提供的添加和删除事件访问器。 The accessor code can connect the interface event to another event in your class or to its own delegate type. 访问者代码可以将接口事件连接到类中的另一个事件或其自己的委托类型。

For example, this will trigger error CS0071: 例如,这将触发错误CS0071:

public delegate void MyEvent(object sender);

interface ITest
{
    event MyEvent Clicked;
}

class Test : Itest
{
    event MyEvent ITest.Clicked;  // CS0071
    public static void Main() { }
}

The correct way would be: 正确的方法是:

public delegate void MyEvent(object sender);

interface ITest
{
    event MyEvent Clicked;
}

class Test : Itest
{
    private MyEvent clicked;

    event MyEvent Itest.Clicked
    {
        add
        {
            clicked += value;
        }

        remove
        {
            clicked -= value;
        }
    }

    public static void Main() { }
}

see Compiler Error CS0071 请参见编译器错误CS0071

This would not actually be an original thought by myself. 这实际上并不是我自己的原创思想。

However, I thought I might respond to this: 但是,我想我可能会回应这个:

"Off the top of my head I don't see any theoretical or practical reason why we could not have field-like explicitly implemented events. Nor do I see any reason why we particularly need to. This may have to remain one of the mysteries of the unknown." “在我的头脑中,我没有看到任何理论上或实际上的原因,为什么我们不能有类似字段的明确实施的事件。我也没有看到任何我们特别需要的原因。这可能仍然是一个谜团未知的。“ -Eric Lippert -Eric Lippert


In Chapter 23 of A Programmer's Introduction to C# , Second Edition, Eric Gunnerson wrote: 程序员C#简介第二版的第23章中,Eric Gunnerson写道:

"[I]f another class also wanted to be called when the button was clicked, the += operator could be used, like this: “[我]另一个类也想在单击按钮时调用,可以使用+ =运算符,如下所示:

button.Click += new Button.ClickHandler(OtherMethodToCall); button.Click + = new Button.ClickHandler(OtherMethodToCall);

Unfortunately, if the other class wasn't careful, it might do the following: 不幸的是,如果其他类不小心,它可能会执行以下操作:

button.Click = new Button.ClickHandler(OtherMethodToCall); button.Click = new Button.ClickHandler(OtherMethodToCall);

This would be bad, as it would mean that our ButtonHandler would be unhooked and only the new method would be called." 这样做会很糟糕,因为这意味着我们的ButtonHandler将被取消挂钩,只会调用新方法。“

... ...

"What is needed is some way of protecting the delegate field so that it is only accessed using += and -=." “需要的是保护委托字段的一些方法,以便只使用+ =和 - =来访问它。”


He goes on over the next few pages to comment on including the add() and remove() methods to implement this behavior; 他接下来几页继续评论包括add()和remove()方法来实现这种行为; being able to write to those methods directly and the consequence of storage allocation for unneeded delegate references. 能够直接写入这些方法以及不需要的委托引用的存储分配结果。

I would add more, but I respect the author too much to do so without his permission. 我会添加更多内容,但是如果没有他的许可,我会过多地尊重作者。 I recommend finding a copy of this book and would recommend anything by Eric Gunnerson in general (blog, etc...) 我建议找一本这本书的副本,并推荐Eric Gunnerson的一般内容(博客等等)

Anyway, I hope this is relevant to the topic and if so, hope it shines light on this "mystery of the unknown"? 无论如何,我希望这与这个话题有关,如果是的话,希望它能够揭示这个“未知的奥秘”? (I was reading this very chapter and searching Stack Overflow for insight into event handler logic considerations when creating custom collections from custom objects) - I only mention this because I claim no specific authority on this particular subject. (我正在阅读本章并搜索Stack Overflow,以便在从自定义对象创建自定义集合时深入了解事件处理程序逻辑注意事项) - 我只提到这一点,因为我声称对此特定主题没有特定权限。 I am merely a student in search of "enlightenment" myself :-) 我自己只是一个寻求“启蒙”的学生:-)

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

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