Como cancelar o registro correto de um manipulador de eventos
Em uma revisão de código, deparei-me com esse fragmento de código (simplificado) para cancelar o registro de um manipulador de eventos:
Fire -= new MyDelegate(OnFire);
Eu pensei que isso não cancela o registro do manipulador de eventos porque cria um novo delegado que nunca havia sido registrado antes. Mas, pesquisando no MSDN, encontrei vários exemplos de código que usam esse idioma.
Então eu comecei um experimento:
internal class Program
{
public delegate void MyDelegate(string msg);
public static event MyDelegate Fire;
private static void Main(string[] args)
{
Fire += new MyDelegate(OnFire);
Fire += new MyDelegate(OnFire);
Fire("Hello 1");
Fire -= new MyDelegate(OnFire);
Fire("Hello 2");
Fire -= new MyDelegate(OnFire);
Fire("Hello 3");
}
private static void OnFire(string msg)
{
Console.WriteLine("OnFire: {0}", msg);
}
}
Para minha surpresa, aconteceu o seguinte:
Fire("Hello 1");
produziu duas mensagens, conforme o esperado.Fire("Hello 2");
produziu uma mensagem!Isso me convenceu de que o não registro
new
delega trabalhos!Fire("Hello 3");
jogou umNullReferenceException
.A depuração do código mostrou que
Fire
énull
depois de cancelar o registro do evento.Eu sei que para manipuladores de eventos e delegados, o compilador gera muito código nos bastidores. Mas ainda não entendo por que meu raciocínio está errado.
o que estou perdendo?
Pergunta adicional: do fato de queFire
énull
quando não há eventos registrados, concluo que em todo lugar em que um evento é disparado, uma verificaçãonull
É necessário.