Diseño del lenguaje C#: implementación explícita de la interfaz de un evento


Pequeña pregunta sobre el diseño del lenguaje C#:))

Si tuviera una interfaz como esta:

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

Es posible implementar explícitamente dicha interfaz usando las propiedades auto-implementadas de C# 3.0:

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

Pero si tuviera un evento en la interfaz:

interface IFoo {
  event EventHandler Event;
}

Y tratando de implementarlo explícitamente usando un evento similar a un campo:

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

Obtendré el siguiente error del compilador:

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

Creo que los eventos de campo son una especie de dualismo para propiedades implementadas automáticamente.

Así que mi pregunta es: ¿cuál es la razón de diseño para tal restricción hecha?

Author: ControlFlow, 2010-02-15

4 answers

Supongo que podría tener que ver con el hecho de que no se puede llamar a una implementación de interfaz explícita de otros miembros de la clase:

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() { }
}

Tenga en cuenta que puede llamar al método mediante upcasting a la interfaz primero:((I)this).DoIt();. Un poco feo, pero funciona.

Si los eventos pudieran implementarse explícitamente como sugiere ControlFlow (el OP), entonces ¿cómo los elevaría realmente? Considere:

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;
}

Aquí ni siquiera se puede elevar el evento por upcasting a la interfaz primero, porque los eventos solo se pueden generar desde dentro de la clase implementadora. Por lo tanto, parece tener perfecto sentido requerir sintaxis de acceso para eventos implementados explícitamente.

 26
Author: Andreas Huber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-07 15:53:09

Pregunta Interesante. Investigué un poco el archivo de notas del idioma y descubrí que esta decisión se tomó el 13 de octubre de 1999, pero las notas no dan una justificación para la decisión.

En la parte superior de mi cabeza no veo ninguna razón teórica o práctica por la que no podríamos tener eventos implementados explícitamente como en el campo. Tampoco veo ninguna razón por la que lo necesitemos en particular. Esto puede tener que seguir siendo uno de los misterios de lo desconocido.

 28
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-15 19:43:33

Cuando implemente explícitamente un evento que se declaró en una interfaz, debe usar proporcionar manualmente los accesores de eventos add y remove que normalmente proporciona el compilador. El código de acceso puede conectar el evento de interfaz a otro evento de su clase o a su propio tipo de delegado.

Por ejemplo, esto activará el error CS0071:

public delegate void MyEvent(object sender);

interface ITest
{
    event MyEvent Clicked;
}

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

El camino correcto sería:

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() { }
}

Ver Error del compilador CS0071

 18
Author: Stécy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-15 20:04:43

Esto no sería realmente un pensamiento original por mí mismo.

Sin embargo, pensé que podría responder a esto:

"En la parte superior de mi cabeza no veo ninguna razón teórica o práctica por la que no podríamos tener eventos implementados explícitamente como en el campo. Tampoco veo ninguna razón por la que lo necesitemos en particular. Esto puede tener que seguir siendo uno de los misterios de lo desconocido." - Eric Lippert


En el Capítulo 23 de La Introducción de un programador a C#, Segunda edición, Eric Gunnerson escribió:

" [I] si otra clase también quería ser llamada cuando se hacía clic en el botón, se podía usar el operador+=, así:

Botón.Haga Clic en el botón += nuevo.ClickHandler(OtherMethodToCall);

Desafortunadamente, si la otra clase no tenía cuidado, podría hacer lo siguiente:

Botón.Haga Clic en = nuevo Botón.ClickHandler(OtherMethodToCall);

Esto sería malo, ya que significaría que nuestro manipulador de botones sería desenganchado y solo se llamaría al nuevo método."

...

"Lo que se necesita es alguna forma de proteger el campo delegado para que solo se acceda usando += y -=."


Continúa en las siguientes páginas para comentar sobre la inclusión de los métodos add() y remove() para implementar este comportamiento; ser capaz de escribir en esos métodos directamente y la consecuencia de la asignación de almacenamiento para referencias de delegados innecesarias.

Yo añadiría más, pero respeto demasiado al autor para hacerlo sin su permiso. Recomiendo encontrar una copia de este libro y recomendaría cualquier cosa por Eric Gunnerson en general (blog, etc...)

De todos modos, espero que esto sea relevante para el tema y si es así, espero que arroje luz sobre este "misterio de lo desconocido"? (Estaba leyendo este mismo capítulo y buscando Stack Overflow para obtener información sobre las consideraciones de la lógica del controlador de eventos al crear colecciones personalizadas a partir de objetos personalizados) - Solo menciono esto porque no pretendo ninguna autoridad específica sobre este tema en particular. Yo soy simplemente un estudiante en busca de la" iluminación": -)

 1
Author: EtherealMonkey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-06 07:34:48