Web Log di Adrian Florea

"You know you've achieved perfection in design, not when you have nothing more to add, but when you have nothing more to take away." Antoine de Saint-Exupery
posts - 440, comments - 2715, trackbacks - 3944

My Links

Archives

Post Categories

Image Galleries

.RO Blogs

.RO People

.RO Sites

Blogs

Furls

Links

vinCitori

Explicitly calling event accessors

Si sa che i metodi corrispondenti agli event accessor devono seguire un pattern di denominazione (vedi CLS Rule 33 e ECMA-335, Partition I, 10.4). Per esempio, l'accessore add deve seguire il pattern:

void add_<EventName> (<DelegateType> handler)

Luca, in questo interessante post, è arrivato ad aver bisogno di richiamare questi event accessor. Provando col compilatore C#, si ottiene l'errore CS0571 ("cannot explicitly call operator or accessor"). Vediamo se, per il seguente snippet, il compilatore C# genera per i metodi add_FooFired e AddFooFired lo stesso codice IL:

class Foo
{
      private FooFiredEvent mFooFired;
      public event FooFiredEvent FooFired
      {
            add
            {
                  mFooFired += value;
            }
            remove
            {
                  mFooFired -= value;
            }
      }
 
      public void AddFooFired(FooFiredEvent value)
      {
            mFooFired += new FooFiredEvent(value);
      }
      public void RemoveFooFired(FooFiredEvent value)
      {
            mFooFired -= new FooFiredEvent(value);
      }
}

Questo è il codice per il corpo del metodo add_FooFired:

.maxstack 8
nop
ldarg.0
dup
ldfld class FooFiredEvent Foo::mFooFired
ldarg.1
call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
castclass FooFiredEvent
stfld class FooFiredEvent Foo::mFooFired
ret

e questo per il corpo del metodo AddFooFired:

.maxstack 8
nop
ldarg.0
dup
ldfld class FooFiredEvent Foo::mFooFired
ldarg.1
ldftn instance void FooFiredEvent::Invoke()
newobj
instance void FooFiredEvent::.ctor(object, native int)
call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
castclass FooFiredEvent
stfld class FooFiredEvent Foo::mFooFired
ret

Si nota il fatto che i due snippet IL non sono perfettamente identici (vedi le righe in rosso). Come fare allora per poter richiamare esplicitamente il metodo add_FooFired? Semplice: scriviamo la classe Foo in Visual J#! :-)

public class Foo
{
      private FooFiredEvent mFooFired;
 
      /** @event */
      public void add_FooFired(FooFiredEvent value)
      {
            mFooFired = (FooFiredEvent)Delegate.Combine(mFooFired, value);
      }
 
      /** @event */
      public void remove_FooFired(FooFiredEvent value)
      {
            mFooFired = (FooFiredEvent)Delegate.Remove(mFooFired, value);
      }
 
      public void AddFooFired(FooFiredEvent value)
      {
            add_FooFired(value);
      }
      public void RemoveFooFired(FooFiredEvent value)
      {
            remove_FooFired(value);
      }
}

Rimanendo in J#, si può richiamare add_FooFired (e per questo abbiamo il metodo "wrapper" AddFooFired), a differenza di C#, dove si ottiene, come abbiamo visto, l'errore CS0571. Così, potete tranquillamente richiamare AddFooFired da qualsiasi linguaggio .NET.

Una domanda: in un commento al post precedente, un ragazzo rumeno mi chiedeva se avessi l'intenzione di scrivere i post in inglese. A voi darebbe fastidio? - l'idea è di non aprire un altro blog

Print | posted on venerdì 20 maggio 2005 17:50 | Filed Under [ Carillon .NET ]

Powered by:
Powered By Subtext Powered By ASP.NET