Si me inscribo para un evento en c # mientras se está enviando, ¿tengo la garantía de que no se me volverá a llamar durante ese despacho?

StackOverflow https://stackoverflow.com/questions/141423

  •  02-07-2019
  •  | 
  •  

Pregunta

En C #, me encuentro ocasionalmente queriendo registrar un método para un evento en medio de un envío de ese mismo evento. Por ejemplo, si tengo una clase que transiciona estados basados ??en envíos sucesivos del mismo evento, es posible que desee que el controlador del primer estado se desregistre y registre el segundo controlador. Sin embargo, no quiero que se envíe el segundo controlador hasta la próxima vez que se active el evento.

La buena noticia es que parece que la implementación de Microsoft de C # se comporta exactamente de esta manera. La sintaxis de registro de eventos se sustituye con una llamada a System.Delegate.Combine, que solo concatena la lista de invocación actual y el nuevo método en una lista separada y la asigna a la propiedad del evento. Esto me da exactamente el comportamiento que quiero.

Entonces, mi pregunta es: ¿está garantizado este comportamiento según el estándar de idioma? Me gusta poder ejecutar mi código C # en otras plataformas en mono y, en general, quiero asegurarme de que no estoy haciendo suposiciones sobre el estándar de idioma en función de su implementación.

No pude encontrar ninguna información definitiva en MSDN.

Si desea un ejemplo específico de lo que estoy hablando, aquí hay un ejemplo:

    delegate void TestDelegate();
    static event TestDelegate TestEvent;

    static void Main (string[] args) {
        TestEvent += TestDelegateInstanceFirst;
        TestEvent();
        TestEvent();
    }

    static void TestDelegateInstanceFirst () {
        Console.WriteLine("First");
        TestEvent += TestDelegateInstanceSecond;
    }

    static void TestDelegateInstanceSecond () {
        Console.WriteLine("Second");
    }

Al menos en Windows, la salida es:

First
First
Second
¿Fue útil?

Solución

Sí, está garantizado.

De la especificación unificada de C # 3.0, sección 15.1:

  

Sin embargo, cuando dos delegados no nulos   los casos se combinan, sus   las listas de invocaciones están concatenadas en   el orden de la izquierda operando luego a la derecha   operando: para formar una nueva lista de invocación,   que contiene dos o más entradas.

Observe la " nueva lista de invocación " ;. Y nuevamente en la sección 15.3:

  

Una vez instanciada, delegar instancias   siempre se refieren al mismo objeto objetivo   y método. Recuerda, cuando dos   Los delegados se combinan, o uno es   eliminado de otro, un nuevo delegado   resultados con su propia lista de invocación;   Las listas de invocación de los delegados.   combinados o eliminados permanecen sin cambios.

Finalmente, MSDN para System.Delegate declara:

  

Los delegados son inmutables; una vez creado,   la lista de invocaciones de un delegado hace   no cambiar.

Sospecho que hay algo en la especificación de la CLI: verificaré si te gustaría, pero espero que estos tres te hayan dado suficiente confianza :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top