c# electrónico - ¿Cómo puedo borrar las suscripciones de eventos en C #?





mi 2017 (9)


Agregue un método a c1 que establecerá 'someEvent' a null ...

class c1
{
    event EventHandler someEvent;
    ResetSubscriptions() {someEvent = null;}
}

Tome la siguiente clase de C #:

c1 {
 event EventHandler someEvent;
}

Si hay muchas suscripciones al evento someEvent c1 y quiero someEvent todas, ¿cuál es la mejor manera de lograrlo? También considere que las suscripciones a este evento podrían ser / son delegados lambdas / anónimos.

Actualmente mi solución es agregar un método ResetSubscriptions() a c1 que establece someEvent en nulo. No sé si esto tiene consecuencias no vistas.




class c1
{
    event EventHandler someEvent;
    ResetSubscriptions() {someEvent = delegate{};}
}

Es mejor usar delegate {} que null




Comentario aburrido extendido conceptual.

Prefiero usar la palabra "controlador de eventos" en lugar de "evento" o "delegar". Y usó la palabra "evento" para otras cosas. En algunos lenguajes de programación (VB.NET, Object Pascal, Objective-C), "evento" se denomina "mensaje" o "señal", e incluso tiene una palabra clave "mensaje" y sintaxis específica de azúcar.

const
  WM_Paint = 998;  // <-- "question" can be done by several talkers
  WM_Clear = 546;

type
  MyWindowClass = class(Window)
    procedure NotEventHandlerMethod_1;
    procedure NotEventHandlerMethod_17;

    procedure DoPaintEventHandler; message WM_Paint; // <-- "answer" by this listener
    procedure DoClearEventHandler; message WM_Clear;
  end;

Y, para responder a ese "mensaje", un "controlador de eventos" responde, ya sea un delegado único o múltiples delegados.

Resumen: "Evento" es la "pregunta", "controlador (es) del evento" es la (s) respuesta (s).




Elimine todos los eventos, suponga que el evento es de tipo "Acción":

Delegate[] dary = TermCheckScore.GetInvocationList();

if ( dary != null )
{
    foreach ( Delegate del in dary )
    {
        TermCheckScore -= ( Action ) del;
    }
}



Esta es mi solución:

public class Foo : IDisposable
{
    private event EventHandler _statusChanged;
    public event EventHandler StatusChanged
    {
        add
        {
            _statusChanged += value;
        }
        remove
        {
            _statusChanged -= value;
        }
    }

    public void Dispose()
    {
        _statusChanged = null;
    }
}

using(new Foo()){/*...*/} llamar a Dispose() o usar el using(new Foo()){/*...*/} patrón using(new Foo()){/*...*/} para using(new Foo()){/*...*/} suscripción de todos los miembros de la lista de invocación.




Desde dentro de la clase, puede establecer la variable (oculta) en nulo. Una referencia nula es la forma canónica de representar efectivamente una lista de invocación vacía.

Desde afuera de la clase, no puedes hacer esto: los eventos básicamente exponen "suscribirse" y "cancelar suscripción" y eso es todo.

Vale la pena ser consciente de lo que realmente hacen los eventos de campo: están creando una variable y un evento al mismo tiempo. Dentro de la clase, terminas haciendo referencia a la variable. Desde afuera, haces referencia al evento.

Vea mi artículo sobre eventos y delegados para más información.




La mejor práctica para borrar a todos los suscriptores es establecer someEvent como nulo agregando otro método público si desea exponer esta funcionalidad al exterior. Esto no tiene consecuencias no vistas. La condición previa es recordar declarar SomeEvent con la palabra clave 'evento'.

Consulte el libro - C # 4.0 en pocas palabras, página 125.

Alguien aquí propuso usar el método Delegate.RemoveAll . Si lo usa, el código de muestra podría seguir el siguiente formulario. Pero es realmente estúpido. ¿Por qué no solo SomeEvent=null dentro de la función ClearSubscribers() ?

   public void ClearSubscribers ()
    {
          SomeEvent = (EventHandler) Delegate.RemoveAll(SomeEvent, SomeEvent);// Then you will find SomeEvent is set to null.
    }



Establecer el evento para anular dentro de la clase funciona. Cuando descarta una clase, siempre debe establecer el evento en nulo, el GC tiene problemas con los eventos y puede no limpiar la clase eliminada si tiene eventos colgantes.




Esto es lo mismo que la mayoría de las respuestas aquí, pero tabularizado para mayor facilidad, y tiene versiones de Visual Studio y .NET para completar.

╔════════════╦════════════╦══════════════╦═════════════╦══════════════╗
║ C# version ║ VS version ║ .NET version ║ CLR version ║ Release date ║
╠════════════╬════════════╬══════════════╬═════════════╬══════════════╣
║    1.0     ║    2002    ║    1.0       ║     1.0     ║   Feb 2002   ║
║    1.2     ║    2003    ║    1.1       ║     1.1     ║   Apr 2003   ║
║    2.0     ║    2005    ║    2.0       ║     2.0     ║   Nov 2005   ║
║            ║            ║    3.0       ║     2.0     ║   Nov 2006   ║
║    3.0     ║    2008    ║    3.5       ║     2.0     ║   Nov 2007   ║
║    4.0     ║    2010    ║    4.0       ║     4       ║   Apr 2010   ║
║    5.0     ║    2012    ║    4.5       ║     4       ║   Aug 2012   ║
║    5.0     ║    2013    ║    4.5.1     ║     4       ║   Oct 2013   ║
║            ║            ║    4.5.2     ║     4       ║   May 2014   ║
║    6.0     ║    2015    ║    4.6       ║     4       ║   Jul 2015   ║
║            ║            ║    4.6.1     ║     4       ║   Nov 2015   ║
║            ║            ║    4.6.2     ║     4       ║   Aug 2016   ║
║    7.0     ║    2017    ║              ║             ║   Mar 2017   ║
║            ║            ║    4.7       ║     4       ║   May 2017   ║
║    7.1     ║ 2017(v15.3)║              ║             ║   Aug 2017   ║
║            ║            ║    4.7.1     ║     4       ║   Oct 2017   ║
║    7.2     ║ 2017(v15.5)║              ║             ║   Dec 2017   ║
║            ║            ║    4.7.2     ║     4       ║   Apr 2018   ║
║    7.3     ║ 2017(v15.7)║              ║             ║   May 2018   ║
╚════════════╩════════════╩══════════════╩═════════════╩══════════════╝

Nota: el desarrollo de .NET es bastante independiente de VS en estos días, no hay correlación entre las versiones de cada uno. Consulte " Versiones y dependencias de .NET Framework " para obtener más información.







c# .net events delegates