proyecto - C#Language Design: implementación de interfaz explícita de un evento
implementar multiples interfaces c# (4)
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 tal 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 tipo campo:
sealed class Foo : IFoo {
event EventHandler IFoo.Event;
}
Obtendré el siguiente error de compilación:
error CS0071: An explicit interface implementation of an event must use event accessor syntax
Creo que los eventos tipo campo son el tipo de dualismo para las propiedades implementadas automáticamente.
Entonces mi pregunta es: ¿cuál es el motivo de diseño para tal restricción?
Al implementar explícitamente un evento que se declaró en una interfaz, debe usar manualmente proporcionar el complemento y eliminar los elementos de acceso de eventos que normalmente proporciona el compilador. El código de acceso puede conectar el evento de interfaz a otro evento en 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() { }
}
La forma correcta 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 el error del compilador CS0071
Esto en realidad no sería un pensamiento original por mi cuenta.
Sin embargo, pensé que podría responder a esto:
"De repente, no veo ninguna razón teórica o práctica por la cual no podamos tener eventos implementados explícitamente como campos. Tampoco veo ninguna razón por la que lo necesitemos en particular. Puede que este tenga que seguir siendo uno de los misterios. de lo desconocido ". -Eric Lippert
En el Capítulo 23 de Introducción a C # , Segunda Edición de un programador, Eric Gunnerson escribió:
"[E] f otra clase también quería que se le llamara cuando se hizo clic en el botón, el operador + = podría usarse, así:
button.Click + = new Button.ClickHandler (OtherMethodToCall);
Desafortunadamente, si la otra clase no tuvo cuidado, podría hacer lo siguiente:
button.Click = new Button.ClickHandler (OtherMethodToCall);
Esto sería malo, ya que significaría que nuestro ButtonHandler sería desenganchado y solo se llamaría al nuevo método ".
...
"Lo que se necesita es alguna forma de proteger el campo de delegado para que solo se acceda usando + = y - =".
Continúa en las siguientes páginas para comentar sobre cómo incluir los métodos add () y remove () para implementar este comportamiento; poder escribir en esos métodos directamente y la consecuencia de la asignación de almacenamiento para referencias delegadas innecesarias.
Agregaría más, pero respeto demasiado al autor por hacerlo sin su permiso. Recomiendo encontrar una copia de este libro y recomendaría cualquier cosa de 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 para conocer las consideraciones lógicas del controlador de eventos al crear colecciones personalizadas a partir de objetos personalizados) - Solo menciono esto porque no reclamo autoridad específica sobre este tema en particular. Simplemente soy un estudiante en busca de la "iluminación" :-)
Interesante pregunta. Hice algunas hurgadas en 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.
Por la parte superior de mi cabeza, no veo ninguna razón teórica o práctica por la cual no podamos tener eventos implementados explícitamente como campos. Tampoco veo ningún motivo por el que lo necesitemos particularmente. Esto puede tener que seguir siendo uno de los misterios de lo desconocido.
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 por upcasting a la interfaz primero: ((I)this).DoIt();
. Un poco feo pero funciona.
Si los eventos podrían implementarse explícitamente como lo sugirió ControlFlow (OP), ¿cómo los plantearía realmente? Considerar:
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 puede plantear el evento mediante la conversión ascendente a la interfaz, ya que los eventos solo se pueden generar desde la clase implementadora. Por lo tanto, parece tener perfecto sentido requerir sintaxis de acceso para eventos implementados explícitamente.