Se il seguente snippet:
delegate void FooFiredEvent();
class Foo
{
public event FooFiredEvent FooFired;
public void RaiseFooFired()
{
if (FooFired != null)
{
FooFired();
}
}
}
lo compiliamo:
csc foo.cs
poi lo disassembliamo :
ildasm foo.exe /out=bar.il
e nel file disassemblato, bar.il, inseriamo la riga in rosso:
.event FooFiredEvent FooFired
{
.addon instance void Foo::add_FooFired(class FooFiredEvent)
.removeon instance void Foo::remove_FooFired(class FooFiredEvent)
.fire instance void Foo::RaiseFooFired()
}
dopodiché lo riassembliamo:
ilasm /exe bar.il
e apriamo il file bar.exe col Reflector impostato per C#, avremo una sorpresa: nel codice disassemblato dell'evento FooFired, è apparsa una sezione, raise, che non c'è ancora nel linguaggio C# :-)
public event FooFiredEvent FooFired
{
[MethodImpl(MethodImplOptions.Synchronized)] add
{
this.FooFired = (FooFiredEvent) Delegate.Combine(this.FooFired, value);
}
[MethodImpl(MethodImplOptions.Synchronized)] remove
{
this.FooFired = (FooFiredEvent) Delegate.Remove(this.FooFired, value);
}
raise
{
if (this.FooFired != null)
{
this.FooFired();
}
}
}
Vediamo cosa dice Serge Lidin di questi firing methods nel suo libro (sottolineatura mia):
"An event can have at most one firing method. The firing method usually boils down to an invocation of the delegate implementing the event. The Visual C# .NET and Visual Basic .NET compilers, for example, never bother to define a firing method for an event—that is, the method invoking the delegate is there, but it is never associated with the event as a firing method. Such an approach contains a certain logic: the firing method is a purely internal affair of the event publisher and need not be exposed to the event subscribers. And because the compilers, as a rule, use the event metadata to facilitate subscription and unsubscription, associating a firing method with an event is not necessary. If an event does have an associated firing method, however, this method must return void".
Se si imposta il Reflector per altri linguaggi (Visual Basic, Delphi) questa "invenzione" non appare più.
(Aggiornamento 24/05/05):
All'interno del framework .NET 2.0.50215 ho trovato via reflection 3
eventi che hanno associato un firing method. La sorpresa delle sorprese è
che tutti questi si trovano nell'assembly Microsoft.VisualBasic.dll :-)
Mi chiedo con quale linguaggio/compilatore sia scritto questo assembly (vuol
dire che quel linguaggio/compilatore permette di associare firing methods agli
eventi!).