I'm wondering about the .NET event model

S

SpookyET

I've been wondering about the proper way of doing events in .net!
This is what I have right now:
-When an event is used by more than one class, you put it in the
namespace, set the sender to object, and MyEventArgs e.
-When an event is only used by one class, you put it inside that class,
set the sender to the class type, and MyEventArgs e.

namespace Foobar
{
public delegate void FoobyEventHandler(object sender, FoobyEventArgs e);
public event FoobyEventHandler Fooby;

class Bar
{
public delegate void BarOnFireEventHandler(Bar sender,
BarOnFireEventArgs e);
public event BarOnFireEventHandler BarOnFire;
}
}

-When an event does not return any data, what is the poind of having an
instance of EventArgs an in System.EventHandler? EventArgs is empty and
not used, what is the poind of wasting a little memory on that object if
it isn't used? Why isn't System.EventHandler declared as:

namespace System
{
public delegate EventHandler(object sender);
}

-EventArgs should have been declared as, since it is useless:

public abstract class EventArgs {}

-The same should have been done with System.Exception to force lazy devs
to create their own exceptions:

public abstract class Exception {}
 
D

Daniel O'Connell [C# MVP]

SpookyET said:
I've been wondering about the proper way of doing events in .net!
This is what I have right now:
-When an event is used by more than one class, you put it in the
namespace, set the sender to object, and MyEventArgs e.
-When an event is only used by one class, you put it inside that class,
set the sender to the class type, and MyEventArgs e.

I would recommend placing it in the namespace. I personally recommend not
placing any type nested in another type unless it needs access to non-public
members.
namespace Foobar
{
public delegate void FoobyEventHandler(object sender, FoobyEventArgs e);
public event FoobyEventHandler Fooby;

An event here isn't syntactically legal. Are you sure you are doing this?
class Bar
{
public delegate void BarOnFireEventHandler(Bar sender, BarOnFireEventArgs
e);
public event BarOnFireEventHandler BarOnFire;
}
}

-When an event does not return any data, what is the poind of having an
instance of EventArgs an in System.EventHandler? EventArgs is empty and
not used, what is the poind of wasting a little memory on that object if
it isn't used? Why isn't System.EventHandler declared as:

It maintains consistency across the system. By defining EventHandler with
said two parameters, it established the pattern that every event has two
parameters, a sender and a set of event arguments. There is probably no
specific reason outside of that.
Beyond that, the memory wasted, if you use best practices, is very low;
probably no more than 100 bytes per appdomain.
namespace System
{
public delegate EventHandler(object sender);
}

-EventArgs should have been declared as, since it is useless:

public abstract class EventArgs {}

Its not useless, EventArgs is a placeholder for empty arguments.
-The same should have been done with System.Exception to force lazy devs
to create their own exceptions:

public abstract class Exception {}

Thats probably true, but it'll never change.
 
S

SpookyET

I know that you can't have an event in the namespace. I made a mistake
there.

The (object sender, EventArgs e) model is not consistent. There are
events that don't have a sender, only a derivative of EventArgs in windows
forms. If there are events without sender, why shouldn't there be events
without EventArgs with just the sender? Why don't you recomment having
Foobar.EventHandler (inside the class name) if only that class is using
it, and having the sender as Foobar instead of object?

By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance void
..ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always using
MulticastDelegate instead of Delegate, even when you don't add events and
the return value is something other than void.


The event part is a little hard to understand. I understand that if
MulticastDelegate had +\- only, it wouldn't allow you to do FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with only one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a class as
a field:

..field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can explain
this stuff to me.

Thanks.
 
D

Daniel O'Connell [C# MVP]

SpookyET said:
I know that you can't have an event in the namespace. I made a mistake
there.

The (object sender, EventArgs e) model is not consistent. There are
events that don't have a sender, only a derivative of EventArgs in windows
forms. If there are events without sender, why shouldn't there be events

I don't know of many of these off hand, but I would say it was a bad choice
not to include a sender, especialy in windows forms. Thinking about it now I
think the sender value is most common in winddows forms but I'm not sure.
I'll do a bit more research tonight and see what I can find. Watch This
Space.
without EventArgs with just the sender? Why don't you recomment having
Foobar.EventHandler (inside the class name) if only that class is using
it, and having the sender as Foobar instead of object?

For code clarity, I always suggest not nesting any class that doesn't have
to be nested. I feel that nested classes are going to be harder to find and
users not using a nice IDE may have a bit of trouble finding that delegate.
I also think that a class being nested suggests that that class uses some of
the internals of the containing class, whcih a delegate will never do.
By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance void
.ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always using
MulticastDelegate instead of Delegate, even when you don't add events and
the return value is something other than void.

That is an oddity of the framework. It seems that once upon a time there
would be both Multicast and Singlecast delegates available. That was
apparently cut, but much of the infrastructure is still there.
The event part is a little hard to understand. I understand that if
MulticastDelegate had +\- only, it wouldn't allow you to do FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with only one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a class as
a field:

.field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can explain
this stuff to me.

When you create an event without accessors in C#, the compiler generates a
set of accessors(add_FoobarEvent and remove_FoobarEvent) which indeed map to
+ and - on the event. It also generates an underying field which the
accessors can operate on as well as what accessing the event gets you.
Consider
public event EventHandler Myevent;

//in some method:
Delegate d = MyEvent;

The compiler transforms the access to MyEvent into an access of hte
underlying field it generates. This lets you consider an event as a normal
field instead of an event property as it actually is. If you want to write
one your selfe

EventHandler myEventField;
public event EventHandler MyEvent
{
add
{
myEventHandler+= value;
}
remove
{
myEventHandler -= value;
}
}

but you now have to reference myEventFIeld to get the backing delegate or to
raise it. MyEvent() won't work.
 
S

SpookyET

-What have you found out?
-I have moved those delegates into the namespace. But I left the sender
as the type of that class instead of Object. Should I set it to object?
-I don't see the point of setting it to object since it is only used by
one class. Type casting is 50% slower for reference types, while for
value types it is a lot slower (boxing/unboxing). I can't recall the
actual number that I have tested, 10 million or 100 million, in any case 1
and many zeros. It took about a second to run, 1.5 seconds to run with
casting to and from object, and almost 6 seconds when boxing/unboxing
(changed it from class to struct). I try to keep casting and boxing to a
minimum. Because of this, System.Collection is pretty useless to me.
Especially since I have to deal with a lot of structs. I hate that
generics weren't released with v1.0. It makes me write a lot of useless
code, and reinvent the wheel.


SpookyET said:
I know that you can't have an event in the namespace. I made a mistake
there.

The (object sender, EventArgs e) model is not consistent. There are
events that don't have a sender, only a derivative of EventArgs in
windows
forms. If there are events without sender, why shouldn't there be
events

I don't know of many of these off hand, but I would say it was a bad
choice
not to include a sender, especialy in windows forms. Thinking about it
now I
think the sender value is most common in winddows forms but I'm not sure.
I'll do a bit more research tonight and see what I can find. Watch This
Space.
without EventArgs with just the sender? Why don't you recomment having
Foobar.EventHandler (inside the class name) if only that class is using
it, and having the sender as Foobar instead of object?

For code clarity, I always suggest not nesting any class that doesn't
have
to be nested. I feel that nested classes are going to be harder to find
and
users not using a nice IDE may have a bit of trouble finding that
delegate.
I also think that a class being nested suggests that that class uses
some of
the internals of the containing class, whcih a delegate will never do.
By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance void
.ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void
EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always using
MulticastDelegate instead of Delegate, even when you don't add events
and
the return value is something other than void.

That is an oddity of the framework. It seems that once upon a time there
would be both Multicast and Singlecast delegates available. That was
apparently cut, but much of the infrastructure is still there.
The event part is a little hard to understand. I understand that if
MulticastDelegate had +\- only, it wouldn't allow you to do
FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with only
one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a class
as
a field:

.field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was
declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can explain
this stuff to me.

When you create an event without accessors in C#, the compiler generates
a
set of accessors(add_FoobarEvent and remove_FoobarEvent) which indeed
map to
+ and - on the event. It also generates an underying field which the
accessors can operate on as well as what accessing the event gets you.
Consider
public event EventHandler Myevent;

//in some method:
Delegate d = MyEvent;

The compiler transforms the access to MyEvent into an access of hte
underlying field it generates. This lets you consider an event as a
normal
field instead of an event property as it actually is. If you want to
write
one your selfe

EventHandler myEventField;
public event EventHandler MyEvent
{
add
{
myEventHandler+= value;
}
remove
{
myEventHandler -= value;
}
}

but you now have to reference myEventFIeld to get the backing delegate
or to
raise it. MyEvent() won't work.
 
D

Daniel O'Connell [C# MVP]

SpookyET said:
-What have you found out?

Not much, all I can see is a vauge pattern and thats it. I havn't had the
time to do any indepth research however. I'll try to reply here if I find
anything else.
-I have moved those delegates into the namespace. But I left the sender
as the type of that class instead of Object. Should I set it to
ject? -I don't see the point of setting it to object since it is only
used by one class. Type casting is 50% slower for reference types, while
for value types it is a lot slower (boxing/unboxing). I can't recall the
actual number that I have tested, 10 million or 100 million, in any case 1
and many zeros. It took about a second to run, 1.5 seconds to run with
casting to and from object, and almost 6 seconds when boxing/unboxing
(changed it from class to struct). I try to keep casting and boxing to a
minimum. Because of this, System.Collection is pretty useless to me.
Especially since I have to deal with a lot of structs. I hate that
generics weren't released with v1.0. It makes me write a lot of useless
code, and reinvent the wheel.

Frankly, that performance really isn't likely to be too important. Are you
writing anything that needs to deal with 100million events in a second? That
seems awful high to me. Same with System.Collection, how many 100million
accesses\sec are you tryign to do?
Anyway, thats irrelevent. Using a specific type as the sender would be ok,
IMHO, if the event doesn't have to be genericly usable. Its a judgement
call, I think, one I wouldn't be opposed to. I would however still recommend
EventArgs in most situations, if your sender doesn't matter than omitting
that may be ok.
SpookyET said:
I know that you can't have an event in the namespace. I made a mistake
there.

The (object sender, EventArgs e) model is not consistent. There are
events that don't have a sender, only a derivative of EventArgs in
windows
forms. If there are events without sender, why shouldn't there be
events

I don't know of many of these off hand, but I would say it was a bad
choice
not to include a sender, especialy in windows forms. Thinking about it
now I
think the sender value is most common in winddows forms but I'm not sure.
I'll do a bit more research tonight and see what I can find. Watch This
Space.
without EventArgs with just the sender? Why don't you recomment having
Foobar.EventHandler (inside the class name) if only that class is using
it, and having the sender as Foobar instead of object?

For code clarity, I always suggest not nesting any class that doesn't
have
to be nested. I feel that nested classes are going to be harder to find
and
users not using a nice IDE may have a bit of trouble finding that
delegate.
I also think that a class being nested suggests that that class uses
some of
the internals of the containing class, whcih a delegate will never do.
By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance void
.ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void
EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always using
MulticastDelegate instead of Delegate, even when you don't add events
and
the return value is something other than void.

That is an oddity of the framework. It seems that once upon a time there
would be both Multicast and Singlecast delegates available. That was
apparently cut, but much of the infrastructure is still there.
The event part is a little hard to understand. I understand that if
MulticastDelegate had +\- only, it wouldn't allow you to do
FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with only
one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a class
as
a field:

.field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was
declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can explain
this stuff to me.

When you create an event without accessors in C#, the compiler generates
a
set of accessors(add_FoobarEvent and remove_FoobarEvent) which indeed
map to
+ and - on the event. It also generates an underying field which the
accessors can operate on as well as what accessing the event gets you.
Consider
public event EventHandler Myevent;

//in some method:
Delegate d = MyEvent;

The compiler transforms the access to MyEvent into an access of hte
underlying field it generates. This lets you consider an event as a
normal
field instead of an event property as it actually is. If you want to
write
one your selfe

EventHandler myEventField;
public event EventHandler MyEvent
{
add
{
myEventHandler+= value;
}
remove
{
myEventHandler -= value;
}
}

but you now have to reference myEventFIeld to get the backing delegate
or to
raise it. MyEvent() won't work.
Thanks.
On Sat, 10 Apr 2004 23:21:15 -0500, Daniel O'Connell [C# MVP]


I've been wondering about the proper way of doing events in .net!
This is what I have right now:
-When an event is used by more than one class, you put it in the
namespace, set the sender to object, and MyEventArgs e.
-When an event is only used by one class, you put it inside that
class,
set the sender to the class type, and MyEventArgs e.

I would recommend placing it in the namespace. I personally recommend
not
placing any type nested in another type unless it needs access to
non-public
members.


namespace Foobar
{
public delegate void FoobyEventHandler(object sender, FoobyEventArgs
e);
public event FoobyEventHandler Fooby;

An event here isn't syntactically legal. Are you sure you are doing
this?


class Bar
{
public delegate void BarOnFireEventHandler(Bar sender,
BarOnFireEventArgs
e);
public event BarOnFireEventHandler BarOnFire;
}
}

-When an event does not return any data, what is the poind of having
an
instance of EventArgs an in System.EventHandler? EventArgs is empty
and
not used, what is the poind of wasting a little memory on that object
if
it isn't used? Why isn't System.EventHandler declared as:


It maintains consistency across the system. By defining EventHandler
with
said two parameters, it established the pattern that every event has
two
parameters, a sender and a set of event arguments. There is probably no
specific reason outside of that.
Beyond that, the memory wasted, if you use best practices, is very low;
probably no more than 100 bytes per appdomain.

namespace System
{
public delegate EventHandler(object sender);
}

-EventArgs should have been declared as, since it is useless:

public abstract class EventArgs {}


Its not useless, EventArgs is a placeholder for empty arguments.

-The same should have been done with System.Exception to force lazy
devs
to create their own exceptions:

public abstract class Exception {}

Thats probably true, but it'll never change.
 
S

SpookyET

I'm writing a BitTorrent client/library. BitTorrent is using a ton of
resources (thousands of sockets opened, and thousands of messages are sent
and received per second). This is why I care about performance related to
casting and boxing and unboxing. There is this Java client, called
Azureus that is using a ton of resources. It isn't uncommon for it to use
200MB of RAM. There is also this cool C++ (native) client called BitComet
that I haven't seen it to go past 30MB of RAM yet. I know that Java has
bad memory management and it is a lot slower since it doens't support
objects on the stack, but since my library is about 60-70% done, I can't
test it to see the performance of casting, boxing and unboxing.

The event that I have seen with no sender is in System.Windows.Forms.Form.

It is boxing int to object and back to int.

C:\Documents and Settings\SpooktyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000


Boxing and unboxing demo start...

Testing boxing and unboxing...

Elapsed time: 5673.346 ms

Boxing and unboxing demo end.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000 /o


Boxing and unboxing demo start...

Testing NO boxing and unboxing...

Elapsed time: 461.4394 ms

Boxing and unboxing demo end.

It is casting System.Exception to object and back to System.Exception.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Casting.exe 100000000


Casting demo start...

Testing casting...

Elapsed time: 14903.95 ms

Casting demo end.


C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimi
zation Demos\Source Code>Casting.exe 100000000 /o


Casting demo start...

Testing NO casting...

Elapsed time: 14177.4 ms

Casting demo end.

Since I'm using a lot of structs, I can't use the System.Collectios
collections.

SpookyET said:
-What have you found out?

Not much, all I can see is a vauge pattern and thats it. I havn't had the
time to do any indepth research however. I'll try to reply here if I find
anything else.
-I have moved those delegates into the namespace. But I left the sender
as the type of that class instead of Object. Should I set it to
ject? -I don't see the point of setting it to object since it is only
used by one class. Type casting is 50% slower for reference types,
while
for value types it is a lot slower (boxing/unboxing). I can't recall
the
actual number that I have tested, 10 million or 100 million, in any
case 1
and many zeros. It took about a second to run, 1.5 seconds to run with
casting to and from object, and almost 6 seconds when boxing/unboxing
(changed it from class to struct). I try to keep casting and boxing to
a
minimum. Because of this, System.Collection is pretty useless to me.
Especially since I have to deal with a lot of structs. I hate that
generics weren't released with v1.0. It makes me write a lot of useless
code, and reinvent the wheel.

Frankly, that performance really isn't likely to be too important. Are
you
writing anything that needs to deal with 100million events in a second?
That
seems awful high to me. Same with System.Collection, how many 100million
accesses\sec are you tryign to do?
Anyway, thats irrelevent. Using a specific type as the sender would be
ok,
IMHO, if the event doesn't have to be genericly usable. Its a judgement
call, I think, one I wouldn't be opposed to. I would however still
recommend
EventArgs in most situations, if your sender doesn't matter than omitting
that may be ok.
I know that you can't have an event in the namespace. I made a
mistake
there.

The (object sender, EventArgs e) model is not consistent. There are
events that don't have a sender, only a derivative of EventArgs in
windows
forms. If there are events without sender, why shouldn't there be
events

I don't know of many of these off hand, but I would say it was a bad
choice
not to include a sender, especialy in windows forms. Thinking about it
now I
think the sender value is most common in winddows forms but I'm not
sure.
I'll do a bit more research tonight and see what I can find. Watch This
Space.
without EventArgs with just the sender? Why don't you recomment
having
Foobar.EventHandler (inside the class name) if only that class is
using
it, and having the sender as Foobar instead of object?

For code clarity, I always suggest not nesting any class that doesn't
have
to be nested. I feel that nested classes are going to be harder to find
and
users not using a nice IDE may have a bit of trouble finding that
delegate.
I also think that a class being nested suggests that that class uses
some of
the internals of the containing class, whcih a delegate will never do.


By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance void
.ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object
sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void
EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always using
MulticastDelegate instead of Delegate, even when you don't add events
and
the return value is something other than void.

That is an oddity of the framework. It seems that once upon a time
there
would be both Multicast and Singlecast delegates available. That was
apparently cut, but much of the infrastructure is still there.


The event part is a little hard to understand. I understand that if
MulticastDelegate had +\- only, it wouldn't allow you to do
FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with only
one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a class
as
a field:

.field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was
declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value')
cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can
explain
this stuff to me.

When you create an event without accessors in C#, the compiler
generates
a
set of accessors(add_FoobarEvent and remove_FoobarEvent) which indeed
map to
+ and - on the event. It also generates an underying field which the
accessors can operate on as well as what accessing the event gets you.
Consider
public event EventHandler Myevent;

//in some method:
Delegate d = MyEvent;

The compiler transforms the access to MyEvent into an access of hte
underlying field it generates. This lets you consider an event as a
normal
field instead of an event property as it actually is. If you want to
write
one your selfe

EventHandler myEventField;
public event EventHandler MyEvent
{
add
{
myEventHandler+= value;
}
remove
{
myEventHandler -= value;
}
}

but you now have to reference myEventFIeld to get the backing delegate
or to
raise it. MyEvent() won't work.

Thanks.
On Sat, 10 Apr 2004 23:21:15 -0500, Daniel O'Connell [C# MVP]


I've been wondering about the proper way of doing events in .net!
This is what I have right now:
-When an event is used by more than one class, you put it in the
namespace, set the sender to object, and MyEventArgs e.
-When an event is only used by one class, you put it inside that
class,
set the sender to the class type, and MyEventArgs e.

I would recommend placing it in the namespace. I personally recommend
not
placing any type nested in another type unless it needs access to
non-public
members.


namespace Foobar
{
public delegate void FoobyEventHandler(object sender, FoobyEventArgs
e);
public event FoobyEventHandler Fooby;

An event here isn't syntactically legal. Are you sure you are doing
this?


class Bar
{
public delegate void BarOnFireEventHandler(Bar sender,
BarOnFireEventArgs
e);
public event BarOnFireEventHandler BarOnFire;
}
}

-When an event does not return any data, what is the poind of having
an
instance of EventArgs an in System.EventHandler? EventArgs is empty
and
not used, what is the poind of wasting a little memory on that
object
if
it isn't used? Why isn't System.EventHandler declared as:


It maintains consistency across the system. By defining EventHandler
with
said two parameters, it established the pattern that every event has
two
parameters, a sender and a set of event arguments. There is probably
no
specific reason outside of that.
Beyond that, the memory wasted, if you use best practices, is very
low;
probably no more than 100 bytes per appdomain.

namespace System
{
public delegate EventHandler(object sender);
}

-EventArgs should have been declared as, since it is useless:

public abstract class EventArgs {}


Its not useless, EventArgs is a placeholder for empty arguments.

-The same should have been done with System.Exception to force lazy
devs
to create their own exceptions:

public abstract class Exception {}

Thats probably true, but it'll never change.
 
D

Daniel O'Connell [C# MVP]

SpookyET said:
I'm writing a BitTorrent client/library. BitTorrent is using a ton of
resources (thousands of sockets opened, and thousands of messages are sent
and received per second). This is why I care about performance related to
casting and boxing and unboxing. There is this Java client, called
Azureus that is using a ton of resources. It isn't uncommon for it to use
200MB of RAM. There is also this cool C++ (native) client called BitComet
that I haven't seen it to go past 30MB of RAM yet. I know that Java has
bad memory management and it is a lot slower since it doens't support
objects on the stack, but since my library is about 60-70% done, I can't
test it to see the performance of casting, boxing and unboxing.

The event that I have seen with no sender is in System.Windows.Forms.Form.

It is boxing int to object and back to int.

C:\Documents and Settings\SpooktyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000


Boxing and unboxing demo start...

Testing boxing and unboxing...

Elapsed time: 5673.346 ms

Boxing and unboxing demo end.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000 /o


Boxing and unboxing demo start...

Testing NO boxing and unboxing...

Elapsed time: 461.4394 ms

Boxing and unboxing demo end.

It is casting System.Exception to object and back to System.Exception.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Casting.exe 100000000


Casting demo start...

Testing casting...

Elapsed time: 14903.95 ms

Casting demo end.


C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimi
zation Demos\Source Code>Casting.exe 100000000 /o


Casting demo start...

Testing NO casting...

Elapsed time: 14177.4 ms

Casting demo end.

Since I'm using a lot of structs, I can't use the System.Collectios
collections.

Yes that is an issue, however I don't know that the data structures is going
to be as big of a deal as file access. Reading the file from disk should be
the largest piece of time. While 200meg is a bit excessive, I think it
should be possible to do in C# at around 50 meg without using structures.
Structures may actually increase memory usage as they are copied as you
travel down the call tree.
SpookyET said:
-What have you found out?

Not much, all I can see is a vauge pattern and thats it. I havn't had the
time to do any indepth research however. I'll try to reply here if I find
anything else.
-I have moved those delegates into the namespace. But I left the sender
as the type of that class instead of Object. Should I set it to
ject? -I don't see the point of setting it to object since it is only
used by one class. Type casting is 50% slower for reference types,
while
for value types it is a lot slower (boxing/unboxing). I can't recall
the
actual number that I have tested, 10 million or 100 million, in any
case 1
and many zeros. It took about a second to run, 1.5 seconds to run with
casting to and from object, and almost 6 seconds when boxing/unboxing
(changed it from class to struct). I try to keep casting and boxing to
a
minimum. Because of this, System.Collection is pretty useless to me.
Especially since I have to deal with a lot of structs. I hate that
generics weren't released with v1.0. It makes me write a lot of useless
code, and reinvent the wheel.

Frankly, that performance really isn't likely to be too important. Are
you
writing anything that needs to deal with 100million events in a second?
That
seems awful high to me. Same with System.Collection, how many 100million
accesses\sec are you tryign to do?
Anyway, thats irrelevent. Using a specific type as the sender would be
ok,
IMHO, if the event doesn't have to be genericly usable. Its a judgement
call, I think, one I wouldn't be opposed to. I would however still
recommend
EventArgs in most situations, if your sender doesn't matter than omitting
that may be ok.
On Sun, 11 Apr 2004 13:57:19 -0500, Daniel O'Connell [C# MVP]


I know that you can't have an event in the namespace. I made a
mistake
there.

The (object sender, EventArgs e) model is not consistent. There are
events that don't have a sender, only a derivative of EventArgs in
windows
forms. If there are events without sender, why shouldn't there be
events

I don't know of many of these off hand, but I would say it was a bad
choice
not to include a sender, especialy in windows forms. Thinking about it
now I
think the sender value is most common in winddows forms but I'm not
sure.
I'll do a bit more research tonight and see what I can find. Watch This
Space.
without EventArgs with just the sender? Why don't you recomment
having
Foobar.EventHandler (inside the class name) if only that class is
using
it, and having the sender as Foobar instead of object?

For code clarity, I always suggest not nesting any class that doesn't
have
to be nested. I feel that nested classes are going to be harder to find
and
users not using a nice IDE may have a bit of trouble finding that
delegate.
I also think that a class being nested suggests that that class uses
some of
the internals of the containing class, whcih a delegate will never do.


By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance void
.ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object
sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void
EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always using
MulticastDelegate instead of Delegate, even when you don't add events
and
the return value is something other than void.

That is an oddity of the framework. It seems that once upon a time
there
would be both Multicast and Singlecast delegates available. That was
apparently cut, but much of the infrastructure is still there.


The event part is a little hard to understand. I understand that if
MulticastDelegate had +\- only, it wouldn't allow you to do
FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with only
one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a class
as
a field:

.field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was
declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value')
cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can
explain
this stuff to me.

When you create an event without accessors in C#, the compiler
generates
a
set of accessors(add_FoobarEvent and remove_FoobarEvent) which indeed
map to
+ and - on the event. It also generates an underying field which the
accessors can operate on as well as what accessing the event gets you.
Consider
public event EventHandler Myevent;

//in some method:
Delegate d = MyEvent;

The compiler transforms the access to MyEvent into an access of hte
underlying field it generates. This lets you consider an event as a
normal
field instead of an event property as it actually is. If you want to
write
one your selfe

EventHandler myEventField;
public event EventHandler MyEvent
{
add
{
myEventHandler+= value;
}
remove
{
myEventHandler -= value;
}
}

but you now have to reference myEventFIeld to get the backing delegate
or to
raise it. MyEvent() won't work.

Thanks.
On Sat, 10 Apr 2004 23:21:15 -0500, Daniel O'Connell [C# MVP]


I've been wondering about the proper way of doing events in .net!
This is what I have right now:
-When an event is used by more than one class, you put it in the
namespace, set the sender to object, and MyEventArgs e.
-When an event is only used by one class, you put it inside that
class,
set the sender to the class type, and MyEventArgs e.

I would recommend placing it in the namespace. I personally recommend
not
placing any type nested in another type unless it needs access to
non-public
members.


namespace Foobar
{
public delegate void FoobyEventHandler(object sender, FoobyEventArgs
e);
public event FoobyEventHandler Fooby;

An event here isn't syntactically legal. Are you sure you are doing
this?


class Bar
{
public delegate void BarOnFireEventHandler(Bar sender,
BarOnFireEventArgs
e);
public event BarOnFireEventHandler BarOnFire;
}
}

-When an event does not return any data, what is the poind of having
an
instance of EventArgs an in System.EventHandler? EventArgs is empty
and
not used, what is the poind of wasting a little memory on that
object
if
it isn't used? Why isn't System.EventHandler declared as:


It maintains consistency across the system. By defining EventHandler
with
said two parameters, it established the pattern that every event has
two
parameters, a sender and a set of event arguments. There is probably
no
specific reason outside of that.
Beyond that, the memory wasted, if you use best practices, is very
low;
probably no more than 100 bytes per appdomain.

namespace System
{
public delegate EventHandler(object sender);
}

-EventArgs should have been declared as, since it is useless:

public abstract class EventArgs {}


Its not useless, EventArgs is a placeholder for empty arguments.

-The same should have been done with System.Exception to force lazy
devs
to create their own exceptions:

public abstract class Exception {}

Thats probably true, but it'll never change.
 
I

intrader

Daniel said:
SpookyET said:
I'm writing a BitTorrent client/library. BitTorrent is using a ton of
resources (thousands of sockets opened, and thousands of messages are
sent
and received per second). This is why I care about performance related
to
casting and boxing and unboxing. There is this Java client, called
Azureus that is using a ton of resources. It isn't uncommon for it to
use
200MB of RAM. There is also this cool C++ (native) client called
BitComet
that I haven't seen it to go past 30MB of RAM yet. I know that Java has
bad memory management and it is a lot slower since it doens't support
objects on the stack, but since my library is about 60-70% done, I can't
test it to see the performance of casting, boxing and unboxing.

The event that I have seen with no sender is in
System.Windows.Forms.Form.

It is boxing int to object and back to int.

C:\Documents and Settings\SpooktyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000


Boxing and unboxing demo start...

Testing boxing and unboxing...

Elapsed time: 5673.346 ms

Boxing and unboxing demo end.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000 /o


Boxing and unboxing demo start...

Testing NO boxing and unboxing...

Elapsed time: 461.4394 ms

Boxing and unboxing demo end.

It is casting System.Exception to object and back to System.Exception.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Casting.exe 100000000


Casting demo start...

Testing casting...

Elapsed time: 14903.95 ms

Casting demo end.


C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimi
zation Demos\Source Code>Casting.exe 100000000 /o


Casting demo start...

Testing NO casting...

Elapsed time: 14177.4 ms

Casting demo end.

Since I'm using a lot of structs, I can't use the System.Collectios
collections.

Yes that is an issue, however I don't know that the data structures is
going to be as big of a deal as file access. Reading the file from disk
should be the largest piece of time. While 200meg is a bit excessive, I
think it should be possible to do in C# at around 50 meg without using
structures. Structures may actually increase memory usage as they are
copied as you travel down the call tree.
-What have you found out?

Not much, all I can see is a vauge pattern and thats it. I havn't had
the time to do any indepth research however. I'll try to reply here if I
find anything else.

-I have moved those delegates into the namespace. But I left the
sender
as the type of that class instead of Object. Should I set it to
ject? -I don't see the point of setting it to object since it is only
used by one class. Type casting is 50% slower for reference types,
while
for value types it is a lot slower (boxing/unboxing). I can't recall
the
actual number that I have tested, 10 million or 100 million, in any
case 1
and many zeros. It took about a second to run, 1.5 seconds to run with
casting to and from object, and almost 6 seconds when boxing/unboxing
(changed it from class to struct). I try to keep casting and boxing to
a
minimum. Because of this, System.Collection is pretty useless to me.
Especially since I have to deal with a lot of structs. I hate that
generics weren't released with v1.0. It makes me write a lot of
useless code, and reinvent the wheel.

Frankly, that performance really isn't likely to be too important. Are
you
writing anything that needs to deal with 100million events in a second?
That
seems awful high to me. Same with System.Collection, how many 100million
accesses\sec are you tryign to do?
Anyway, thats irrelevent. Using a specific type as the sender would be
ok,
IMHO, if the event doesn't have to be genericly usable. Its a judgement
call, I think, one I wouldn't be opposed to. I would however still
recommend
EventArgs in most situations, if your sender doesn't matter than
omitting that may be ok.



On Sun, 11 Apr 2004 13:57:19 -0500, Daniel O'Connell [C# MVP]


I know that you can't have an event in the namespace. I made a
mistake
there.

The (object sender, EventArgs e) model is not consistent. There are
events that don't have a sender, only a derivative of EventArgs in
windows
forms. If there are events without sender, why shouldn't there be
events

I don't know of many of these off hand, but I would say it was a bad
choice
not to include a sender, especialy in windows forms. Thinking about it
now I
think the sender value is most common in winddows forms but I'm not
sure.
I'll do a bit more research tonight and see what I can find. Watch
This Space.
without EventArgs with just the sender? Why don't you recomment
having
Foobar.EventHandler (inside the class name) if only that class is
using
it, and having the sender as Foobar instead of object?

For code clarity, I always suggest not nesting any class that doesn't
have
to be nested. I feel that nested classes are going to be harder to
find and
users not using a nice IDE may have a bit of trouble finding that
delegate.
I also think that a class being nested suggests that that class uses
some of
the internals of the containing class, whcih a delegate will never do.


By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance void
.ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object
sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void
EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always using
MulticastDelegate instead of Delegate, even when you don't add events
and
the return value is something other than void.

That is an oddity of the framework. It seems that once upon a time
there
would be both Multicast and Singlecast delegates available. That was
apparently cut, but much of the infrastructure is still there.


The event part is a little hard to understand. I understand that if
MulticastDelegate had +\- only, it wouldn't allow you to do
FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with
only one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a
class as
a field:

.field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was
declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value') cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value')
cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can
explain
this stuff to me.

When you create an event without accessors in C#, the compiler
generates
a
set of accessors(add_FoobarEvent and remove_FoobarEvent) which indeed
map to
+ and - on the event. It also generates an underying field which the
accessors can operate on as well as what accessing the event gets you.
Consider
public event EventHandler Myevent;

//in some method:
Delegate d = MyEvent;

The compiler transforms the access to MyEvent into an access of hte
underlying field it generates. This lets you consider an event as a
normal
field instead of an event property as it actually is. If you want to
write
one your selfe

EventHandler myEventField;
public event EventHandler MyEvent
{
add
{
myEventHandler+= value;
}
remove
{
myEventHandler -= value;
}
}

but you now have to reference myEventFIeld to get the backing delegate
or to
raise it. MyEvent() won't work.

Thanks.
On Sat, 10 Apr 2004 23:21:15 -0500, Daniel O'Connell [C# MVP]


I've been wondering about the proper way of doing events in .net!
This is what I have right now:
-When an event is used by more than one class, you put it in the
namespace, set the sender to object, and MyEventArgs e.
-When an event is only used by one class, you put it inside that
class,
set the sender to the class type, and MyEventArgs e.

I would recommend placing it in the namespace. I personally
recommend not
placing any type nested in another type unless it needs access to
non-public
members.


namespace Foobar
{
public delegate void FoobyEventHandler(object sender,
FoobyEventArgs e);
public event FoobyEventHandler Fooby;

An event here isn't syntactically legal. Are you sure you are doing
this?


class Bar
{
public delegate void BarOnFireEventHandler(Bar sender,
BarOnFireEventArgs
e);
public event BarOnFireEventHandler BarOnFire;
}
}

-When an event does not return any data, what is the poind of
having an
instance of EventArgs an in System.EventHandler? EventArgs is
empty and
not used, what is the poind of wasting a little memory on that
object
if
it isn't used? Why isn't System.EventHandler declared as:


It maintains consistency across the system. By defining EventHandler
with
said two parameters, it established the pattern that every event has
two
parameters, a sender and a set of event arguments. There is probably
no
specific reason outside of that.
Beyond that, the memory wasted, if you use best practices, is very
low;
probably no more than 100 bytes per appdomain.

namespace System
{
public delegate EventHandler(object sender);
}

-EventArgs should have been declared as, since it is useless:

public abstract class EventArgs {}


Its not useless, EventArgs is a placeholder for empty arguments.

-The same should have been done with System.Exception to force lazy
devs
to create their own exceptions:

public abstract class Exception {}

Thats probably true, but it'll never change.
Fascinating thread!
 
S

SpookyET

What's so fascinating about it?

Daniel said:
SpookyET said:
I'm writing a BitTorrent client/library. BitTorrent is using a ton of
resources (thousands of sockets opened, and thousands of messages are
sent
and received per second). This is why I care about performance related
to
casting and boxing and unboxing. There is this Java client, called
Azureus that is using a ton of resources. It isn't uncommon for it to
use
200MB of RAM. There is also this cool C++ (native) client called
BitComet
that I haven't seen it to go past 30MB of RAM yet. I know that Java
has
bad memory management and it is a lot slower since it doens't support
objects on the stack, but since my library is about 60-70% done, I
can't
test it to see the performance of casting, boxing and unboxing.

The event that I have seen with no sender is in
System.Windows.Forms.Form.

It is boxing int to object and back to int.

C:\Documents and Settings\SpooktyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000


Boxing and unboxing demo start...

Testing boxing and unboxing...

Elapsed time: 5673.346 ms

Boxing and unboxing demo end.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Boxing.exe 100000000 /o


Boxing and unboxing demo start...

Testing NO boxing and unboxing...

Elapsed time: 461.4394 ms

Boxing and unboxing demo end.

It is casting System.Exception to object and back to System.Exception.

C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimization Demos\Source
Code>Casting.exe 100000000


Casting demo start...

Testing casting...

Elapsed time: 14903.95 ms

Casting demo end.


C:\Documents and Settings\SpookyET\My Documents\Visual Studio
Projects\Classes and Tutorials\Code Optimi
zation Demos\Source Code>Casting.exe 100000000 /o


Casting demo start...

Testing NO casting...

Elapsed time: 14177.4 ms

Casting demo end.

Since I'm using a lot of structs, I can't use the System.Collectios
collections.

Yes that is an issue, however I don't know that the data structures is
going to be as big of a deal as file access. Reading the file from disk
should be the largest piece of time. While 200meg is a bit excessive, I
think it should be possible to do in C# at around 50 meg without using
structures. Structures may actually increase memory usage as they are
copied as you travel down the call tree.
On Thu, 15 Apr 2004 11:37:01 -0500, Daniel O'Connell [C# MVP]


-What have you found out?

Not much, all I can see is a vauge pattern and thats it. I havn't had
the time to do any indepth research however. I'll try to reply here
if I
find anything else.

-I have moved those delegates into the namespace. But I left the
sender
as the type of that class instead of Object. Should I set it to
ject? -I don't see the point of setting it to object since it is
only
used by one class. Type casting is 50% slower for reference types,
while
for value types it is a lot slower (boxing/unboxing). I can't
recall
the
actual number that I have tested, 10 million or 100 million, in any
case 1
and many zeros. It took about a second to run, 1.5 seconds to run
with
casting to and from object, and almost 6 seconds when boxing/unboxing
(changed it from class to struct). I try to keep casting and boxing
to
a
minimum. Because of this, System.Collection is pretty useless to me.
Especially since I have to deal with a lot of structs. I hate that
generics weren't released with v1.0. It makes me write a lot of
useless code, and reinvent the wheel.

Frankly, that performance really isn't likely to be too important. Are
you
writing anything that needs to deal with 100million events in a
second?
That
seems awful high to me. Same with System.Collection, how many
100million
accesses\sec are you tryign to do?
Anyway, thats irrelevent. Using a specific type as the sender would be
ok,
IMHO, if the event doesn't have to be genericly usable. Its a
judgement
call, I think, one I wouldn't be opposed to. I would however still
recommend
EventArgs in most situations, if your sender doesn't matter than
omitting that may be ok.



On Sun, 11 Apr 2004 13:57:19 -0500, Daniel O'Connell [C# MVP]


I know that you can't have an event in the namespace. I made a
mistake
there.

The (object sender, EventArgs e) model is not consistent. There
are
events that don't have a sender, only a derivative of EventArgs in
windows
forms. If there are events without sender, why shouldn't there be
events

I don't know of many of these off hand, but I would say it was a bad
choice
not to include a sender, especialy in windows forms. Thinking about
it
now I
think the sender value is most common in winddows forms but I'm not
sure.
I'll do a bit more research tonight and see what I can find. Watch
This Space.
without EventArgs with just the sender? Why don't you recomment
having
Foobar.EventHandler (inside the class name) if only that class is
using
it, and having the sender as Foobar instead of object?

For code clarity, I always suggest not nesting any class that
doesn't
have
to be nested. I feel that nested classes are going to be harder to
find and
users not using a nice IDE may have a bit of trouble finding that
delegate.
I also think that a class being nested suggests that that class uses
some of
the internals of the containing class, whcih a delegate will never
do.


By the way, I know that public delegate void FoobarDelegate(object
sender, EventArgs e); is syntax sugar for:

public class FoobarDelegate : MulticastDelegate {...}

.class public auto sealed ansi FoobarDelegate
extends [mscorlib]System.MulticastDelegate
{

.method public hidebysig specialname rtspecialname instance
void
.ctor(object 'object', native int 'method') runtime managed
{
}

.method public virtual hidebysig instance void Invoke(object
sender,
class [mscorlib]System.EventArgs e) runtime managed
{
}

.method public virtual hidebysig newslot instance class
[mscorlib]System.IAsyncResult BeginInvoke(object sender, class
[mscorlib]System.EventArgs e, class [mscorlib]System.AsyncCallback
callback, object 'object') runtime managed
{
}

.method public virtual hidebysig newslot instance void
EndInvoke(class
[mscorlib]System.IAsyncResult result) runtime managed
{
}
}

This would be an inner class if you do Foobar.FoobarDelegate.
I've been playing with delegate declarations, and it is always
using
MulticastDelegate instead of Delegate, even when you don't add
events
and
the return value is something other than void.

That is an oddity of the framework. It seems that once upon a time
there
would be both Multicast and Singlecast delegates available. That was
apparently cut, but much of the infrastructure is still there.


The event part is a little hard to understand. I understand that
if
MulticastDelegate had +\- only, it wouldn't allow you to do
FoobarDelegate
f = (FoobarDelegate) foo;. It would have forced you to work with
only one
reference of FoobarDelegate.

You have this in a class, which seems to me that it is masking a
class as
a field:

.field private class DataStructuresTests.FoobarDelegate FoobarEvent

Then you have the stuff bellow in the class where the event was
declared:

.method public hidebysig specialname instance void
add_FoobarEvent(class DataStructuresTests.FoobarDelegate 'value')
cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

.method public hidebysig specialname instance void
remove_FoobarEvent(class DataStructuresTests.FoobarDelegate
'value')
cil
managed synchronized
{
.maxstack 8

IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0007: ldarg.1
IL_0008: call class [mscorlib]System.Delegate
[mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
class
[mscorlib]System.Delegate)
IL_000d: castclass class DataStructuresTests.FoobarDelegate
IL_0012: stfld class DataStructuresTests.FoobarDelegate
DataStructuresTests.Tester::FoobarEvent
IL_0017: ret
}

And then, you have this:

.event class DataStructuresTests.FoobarDelegate FoobarEvent
{
.addon instance void
DataStructuresTests.Tester::add_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
.removeon instance void
DataStructuresTests.Tester::remove_FoobarEvent(class
DataStructuresTests.FoobarDelegate)
}


Does .addon and .removeon stand for +/-? Maybe some of you can
explain
this stuff to me.

When you create an event without accessors in C#, the compiler
generates
a
set of accessors(add_FoobarEvent and remove_FoobarEvent) which
indeed
map to
+ and - on the event. It also generates an underying field which the
accessors can operate on as well as what accessing the event gets
you.
Consider
public event EventHandler Myevent;

//in some method:
Delegate d = MyEvent;

The compiler transforms the access to MyEvent into an access of hte
underlying field it generates. This lets you consider an event as a
normal
field instead of an event property as it actually is. If you want to
write
one your selfe

EventHandler myEventField;
public event EventHandler MyEvent
{
add
{
myEventHandler+= value;
}
remove
{
myEventHandler -= value;
}
}

but you now have to reference myEventFIeld to get the backing
delegate
or to
raise it. MyEvent() won't work.

Thanks.
On Sat, 10 Apr 2004 23:21:15 -0500, Daniel O'Connell [C# MVP]


I've been wondering about the proper way of doing events in .net!
This is what I have right now:
-When an event is used by more than one class, you put it in the
namespace, set the sender to object, and MyEventArgs e.
-When an event is only used by one class, you put it inside that
class,
set the sender to the class type, and MyEventArgs e.

I would recommend placing it in the namespace. I personally
recommend not
placing any type nested in another type unless it needs access to
non-public
members.


namespace Foobar
{
public delegate void FoobyEventHandler(object sender,
FoobyEventArgs e);
public event FoobyEventHandler Fooby;

An event here isn't syntactically legal. Are you sure you are
doing
this?


class Bar
{
public delegate void BarOnFireEventHandler(Bar sender,
BarOnFireEventArgs
e);
public event BarOnFireEventHandler BarOnFire;
}
}

-When an event does not return any data, what is the poind of
having an
instance of EventArgs an in System.EventHandler? EventArgs is
empty and
not used, what is the poind of wasting a little memory on that
object
if
it isn't used? Why isn't System.EventHandler declared as:


It maintains consistency across the system. By defining
EventHandler
with
said two parameters, it established the pattern that every event
has
two
parameters, a sender and a set of event arguments. There is
probably
no
specific reason outside of that.
Beyond that, the memory wasted, if you use best practices, is very
low;
probably no more than 100 bytes per appdomain.

namespace System
{
public delegate EventHandler(object sender);
}

-EventArgs should have been declared as, since it is useless:

public abstract class EventArgs {}


Its not useless, EventArgs is a placeholder for empty arguments.

-The same should have been done with System.Exception to force
lazy
devs
to create their own exceptions:

public abstract class Exception {}

Thats probably true, but it'll never change.
Fascinating thread!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top