On Tue, 28 Oct 2008 13:30:51 -0700, puzzlecracker <ir*********@gmail.com>
wrote:
Is there a sample implementation of events stored in dictionary to
save memory? It's sounds like an interesting approach, even though
it's unrelated to the question itself, thought it may become clearer
to me when I see the example, a good one.
I'm not sure what you mean by "unrelated to the question itself". In that
an event is an abstraction that need not be implemented using a simple
delegate field, I think your follow-up is in face reasonably related to
the original question.
As for such an example, here's a sort of brain-dead version of what it
might look like:
class Base
{
Dictionary<string, Delegate_dictEventHandlers = new
Dictionary<string, Delegate>();
protected void _AddEventHandler(string strEventName, Delegate
handler)
{
Delegate handlerCur;
if (_dictEventHandlers.TryGetValue(strEventName, out
handlerCur))
{
handlerCur += handler;
}
else
{
handlerCur = null;
}
_dictEventHandlers[strEventName] = handlerCur;
}
protected void _RemoveEventHandler(string strEventName, Delegate
handler)
{
Delegate handlerCur;
if (_dictEventHandlers.TryGetValue(strEventName, out
handlerCur))
{
handlerCur -= handler;
_dictEventHandlers[strEventName] = handlerCur;
}
}
public event EventHandler BaseEvent
{
add { _AddEventHandler("BaseEvent", value); }
remove { _RemoveEventHandler("BaseEvent", value); }
}
}
class Derived : Base
{
public event EventHandler DerivedEvent
{
add { _AddEventHandler("DerivedEvent", value); }
remove { _RemoveEventHandler("DerivedEvent, value); }
}
}
I say "brain-dead" because using a string as the key for the dictionary
isn't the most efficient approach a class like this might take. But it's
simple, and actually doesn't add _that_ much overhead.
Anyway, hopefully the example is sufficient to illustrate the idea. Note
that unless an event is actually subscribed to, the dictionary never winds
up storing anything for that actual event. The approach itself has some
overhead, in the form of the dictionary itself (which even when empty,
takes up _some_ room), and of course the keys (which even if they are
Guids or something like that, take up some space in the executable). But
not that the keys are not per-instance, and if you've got lots of events,
the space taken by the dictionary itself is tiny compared to how big an
instance would be to store all those null references that are almost never
used if the default implementation was used.
>The other thing you're missing is that an event _encapsulates_ the Â*
delegate. Â*That is, while the semantics are similar, only the class Â*
declaring the event has access to the storage. Â*Just as with a
property, Â*
code outside the class is forced to go through the accessor methods
(add Â*
and remove for events), and cannot modify the underlying delegate Â*
directly. Â*Simply using a delegate would not accomplish this.
So it is meant for a user to prevent exposing the delegate instance to
the event? So events becomes just an anonymous placeholder for a
delegate.
I don't know what you mean by "anonymous placeholder". They're neither
anonymous nor just a placeholder. They are named, and they have actual
implementation behind them. It's just that, just like a property does, an
event creates an encapsulation of functionality that hides the underlying
implementation from the user code.
It's basically a type of interface or data contract if you will. An event
promises to the user certain semantics -- add and remove -- along with a
specific data type (whatever delegate type is used for the event). That's
_all_ the user is promised, and inside the event implementation, the class
is free to implement it however they like.
Now, just as in C# 3.0 there are automatic properties, events in C# have
an automatic, or default, implementation in which the compiler creates the
add and remove methods for you, as well as a private field for storing the
state of the event.
Unlike the case with automatic properties, for an automatic event the
class declaring the event still needs to be able to distinguish between
the event itself and the field storing the state, because the event itself
can't be read. So it's a _little_ different from a property in that
respect; when the declaring class uses the event name, it gets the field,
but when any other code uses the event name, it gets the event itself.
But other than that, if you understand why properties are useful, you
should also understand why the similar encapsulation an event provides is
useful.
Pete