14
Curiosity is bliss Julien Couvreur's programming blog and more « C# Delegates strike back | Archive list | Better async programming in .Net 5.0 (latest) C# events vs. delegates We have looked at delegates and their implementation in two previous articles. But if you searched some more information about delegates on the web, you surely noticed they are almost always associated with the "event" construct. Online event tutorials make it look like events are something pretty different from regular delegates instance, although related. Events are usually explained as if they were a special type or construct. But we will see they really are a modifier on the delegate type, which adds some restrictions that the compiler enforces and also adds two accessors (similar to the get and set for properties). A first look at event vs. regular delegate As I was finishing my previous posts on delegates, another C# construct started baking my noodle: events. Events definitely seem related to delegates, but I couldn't figure out how they differ. From their syntax, events look like a field holding a combination of delegates, which is just what a multicast delegate is. Also they support the same combination operators as delegates (+ and -). In the following sample program (which has no useful functionality what-so-ever) we see that msgNotifier (with event construct) and msgNotifier2 (plain delegate) appear to behave exactly the same way for all intents and purposes. using System; namespace EventAndDelegate { delegate void MsgHandler(string s); class Class1 { public static event MsgHandler msgNotifier; public static MsgHandler msgNotifier2; Host your Company Event Great place for a company party! LuckyStrike Houston, TX www.bowlluckystrike.cDownload COBOL Editor Code comprehension, maintenance Metrics, graphs and documentation www.scitools.com Complex Event Processing Enhance Applications That Stream Data With Event Stream Processing! www.progress.com/apMerrill Edge Investing Open A $0 Trade Self-Directed Online Brokerage Account Today. www.MerrillEdge.com Page 1 of 14 Curiosity is bliss: C# events vs. delegates 5/12/2011 http://blog.monstuff.com/archives/000040.html

C# Delegates Event Whitepaper

  • Upload
    sreek1

  • View
    80

  • Download
    0

Embed Size (px)

Citation preview

Page 1: C# Delegates Event Whitepaper

Curiosity is blissJulien Couvreur's programming blog and more

« C# Delegates strike back | Archive list | Better async programming in .Net 5.0 (latest)

C# events vs. delegates

We have looked at delegates and their implementation in two previous articles. But if

you searched some more information about delegates on the web, you surely noticed

they are almost always associated with the "event" construct.

Online event tutorials make it look like events are something pretty different from

regular delegates instance, although related. Events are usually explained as if they

were a special type or construct. But we will see they really are a modifier on the

delegate type, which adds some restrictions that the compiler enforces and also adds

two accessors (similar to the get and set for properties).

A first look at event vs. regular delegate

As I was finishing my previous posts on delegates, another C# construct started baking

my noodle: events. Events definitely seem related to delegates, but I couldn't figure out

how they differ.

From their syntax, events look like a field holding a combination of delegates, which is

just what a multicast delegate is. Also they support the same combination operators as

delegates (+ and -).

In the following sample program (which has no useful functionality what-so-ever) we

see that msgNotifier (with event construct) and msgNotifier2 (plain delegate) appear

to behave exactly the same way for all intents and purposes.

using System;

namespace EventAndDelegate

{

delegate void MsgHandler(string s);

class Class1

{

public static event MsgHandler msgNotifier;

public static MsgHandler msgNotifier2;

Host your Company EventGreat place for a company party! LuckyStrike Houston, TXwww.bowlluckystrike.c…

Download COBOL EditorCode comprehension, maintenance Metrics, graphs and documentationwww.scitools.com

Complex Event ProcessingEnhance Applications That Stream Data With Event Stream Processing!www.progress.com/ap…

Merrill Edge InvestingOpen A $0 Trade Self-Directed Online Brokerage Account Today.www.MerrillEdge.com

Page 1 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 2: C# Delegates Event Whitepaper

[STAThread]

static void Main(string[] args)

{

Class1.msgNotifier += new MsgHandler(PipeNull);

Class1.msgNotifier2 += new MsgHandler(PipeNull);

Class1.msgNotifier("test");

Class1.msgNotifier2("test2");

}

static void PipeNull(string s)

{

return;}

}

}

Looking at the IL code for the Main method in this code, you will notice that both delegates

msgNotifier and msgNotifier2 are again used exactly the same way.

.method private hidebysig static void Main(string[] args) cil managed

{

.entrypoint

.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01

00 00 00 )

// Code size 95 (0x5f)

.maxstack 4

IL_0000: ldsfld class EventAndDelegate.MsgHandler

EventAndDelegate.Class1::msgNotifier

IL_0005: ldnull

IL_0006: ldftn void EventAndDelegate.Class1::PipeNull(string)

IL_000c: newobj instance void EventAndDelegate.MsgHandler::.ctor(object,

native int)

IL_0011: call class [mscorlib]System.Delegate [mscorlib]

System.Delegate::Combine(class [mscorlib]System.Delegate,

class [mscorlib]System.Delegate)

IL_0016: castclass EventAndDelegate.MsgHandler

IL_001b: stsfld class EventAndDelegate.MsgHandler

EventAndDelegate.Class1::msgNotifier

IL_0020: ldsfld class EventAndDelegate.MsgHandler

EventAndDelegate.Class1::msgNotifier2

IL_0025: ldnull

IL_0026: ldftn void EventAndDelegate.Class1::PipeNull(string)

IL_002c: newobj instance void EventAndDelegate.MsgHandler::.ctor(object,

native int)

IL_0031: call class [mscorlib]System.Delegate [mscorlib]

System.Delegate::Combine(class [mscorlib]System.Delegate,

class [mscorlib]System.Delegate)

IL_0036: castclass EventAndDelegate.MsgHandler

IL_003b: stsfld class EventAndDelegate.MsgHandler

EventAndDelegate.Class1::msgNotifier2

IL_0040: ldsfld class EventAndDelegate.MsgHandler

EventAndDelegate.Class1::msgNotifier

Page 2 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 3: C# Delegates Event Whitepaper

IL_0045: ldstr "test"

IL_004a: callvirt instance void EventAndDelegate.MsgHandler::Invoke

(string)

IL_004f: ldsfld class EventAndDelegate.MsgHandler

EventAndDelegate.Class1::msgNotifier2

IL_0054: ldstr "test2"

IL_0059: callvirt instance void EventAndDelegate.MsgHandler::Invoke

(string)

IL_005e: ret

} // end of method Class1::Main

Looking at the C# keywords list on MSDN. It turns out that event is only a modifier. The question is

what modification does it bring?

The added value of event

Events and interfaces

First, an event can be included in an interface declaration, whereas a field cannot. This is the most

important behavior change introduced by the event modifier. For example:

interface ITest

{

event MsgHandler msgNotifier; // compiles

MsgHandler msgNotifier2; // error CS0525: Interfaces cannot contain

fields

}

class TestClass : ITest

{

public event MsgHandler msgNotifier; // When you implement the interface,

you need to implement the event too

static void Main(string[] args) {}

}

Event invocation

Furthermore, an event can only be invoked from within the class that declared it, whereas a delegate

field can be invoked by whoever has access to it. For example:

using System;

namespace EventAndDelegate

{

delegate void MsgHandler(string s);

class Class1

{

public static event MsgHandler msgNotifier;

public static MsgHandler msgNotifier2;

Page 3 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 4: C# Delegates Event Whitepaper

static void Main(string[] args)

{

new Class2().test();

}

}

class Class2

{

public void test()

{

Class1.msgNotifier("test"); // error CS0070: The event

'EventAndDelegate.Class1.msgNotifier' can only appear on the left hand side

of += or -= (except when used from within the type

'EventAndDelegate.Class1')

Class1.msgNotifier2("test2"); // compiles fine

}

}

}

This restriction on invocations is quite strong. Even derived classes from the class declaring the event

aren't allowed to fire the event. A way to deal with this is to have a protected virtual method to trigger

the event.

Event accessors

Also, events come with a pair of accessor methods. They have an add and remove method.

This is similar to properties, which offer a pair of get and set methods.

You are allowed to override these accessors, as shown in examples 2 and 3 on this C# event modifier

reference on MSDN. Although I don't see how example 2 is useful, you could imagine that you could

have a custom add to send some notification or write a log entry, for example, when a listener is

added to your event.

The add and remove accessors need to be customized together, otherwise you get error CS0065

('Event.TestClass.msgNotifier' : event property must have both add and remove accessors).

Looking at the IL for a previous example, where the event accessors weren't customized, I noticed

compiler generated methods (add_msgNotifier and remove_msgNotifier) for the msgNotifier event.

But they weren't used, and whenever the event was accessed the same IL code was duplicated

(inlined).

But when you customize these accessors and look at the IL again, you'll notice that the generated

accessors are now used when you access the event. For example, this code :

using System;

Page 4 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 5: C# Delegates Event Whitepaper

namespace Event

{

public delegate void MsgHandler(string msg);

interface ITest

{

event MsgHandler msgNotifier; // compiles

MsgHandler msgNotifier2; // error CS0525: Interfaces cannot contain

fields

}

class TestClass : ITest

{

public event MsgHandler msgNotifier

{

add

{

Console.WriteLine("hello");

msgNotifier += value;

}

}

static void Main(string[] args)

{

new TestClass().msgNotifier += new MsgHandler(TestDel);

}

static void TestDel(string x)

{

}

}

}

brings the following IL for the Main method:

{

.entrypoint

// Code size 23 (0x17)

.maxstack 4

IL_0000: newobj instance void Event.TestClass::.ctor()

IL_0005: ldnull

IL_0006: ldftn void Event.TestClass::TestDel(string)

IL_000c: newobj instance void Event.MsgHandler::.ctor(object,

native int)

IL_0011: call instance void Event.TestClass::add_msgNotifier(class

Event.MsgHandler)

IL_0016: ret

} // end of method TestClass::Main

Event signature

Finally, even though C# allows it, the .NET framework adds a restriction on the signature of delegates

Page 5 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 6: C# Delegates Event Whitepaper

that can be used as events. The signature should be foo(object source, EventArgs e), where source is

the object that fired the event and e contains any additional information about the event.

Conclusion

We have seen that the event keyword is a modifier for a delegate declaration that allows it to be

included in an interface, constraints it invocation from within the class that declares it, provides it

with a pair of customizable accessors (add and remove) and forces the signature of the delegate (when

used within the .NET framework).

Links

Events Tutorial on MSDN.

Event keyword reference on MSDN.

Update:

One question that was left open and that was brought up by some readers was the rationale behind

the restriction on event invocation: "Invoking an event can only be done from within the class that

declared the event". I am still trying to get a definitive answer via some internal discussion lists, but

here is the best idea that I got so far.

I think it is because of a syntaxic problem. When you put an access specifier ("private", "public", ...) on

an event it controls who can register or listen to that event.

The question is how would you specify the access control for the invocation of that event. You can't

use the same specifiers because it would be confusing.

The solution is to have the event invocation be completely restricted and allow the coder to write a

custom invocation method on which he can easily control the access, which is the way it is now.

An alternate solution might have been to use some kind of attribute on the event [EventAccess

(PublicInvocation)] or [EventAccess(ProtectedInvocation)]. But that seems uglier because it requires

reflection to control the access at runtime.

Update:

Race condition in common event firing pattern:

As any other object, an event object needs to be treated with care in multi-threaded scenarios.

Page 6 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 7: C# Delegates Event Whitepaper

JayBaz and EricGu point out a frequent race condition mistake with event firing:

if (Click != null)

Click(arg1, arg2);

Note that all the MSDN samples I have seen use the dangerous pattern.

Posted by Julien on April 29, 2003. Permalink

Comments

Great material. Exactly what I needed to understand. The Visual Studio documentation didn't make this

clear at all.

Notes:

- Your use of the phrase "delegate declaration" is ambiguous: do you mean the declaration of a delegate

*type* [e.g.: public delegate MyDelegate(int i)] or the declaration of a delegate *object* [e.g.: MyDelegate

a] ?

- I would like to know the rationale behind why the event's invocation is restricted to the declaring class

Posted by: JulioB at October 2, 2003 10:57 PM

Glad this was useful to you.

You're right, from the ECMA C# language specification, "delegate declaration" is the term for the declaration

of the delegate type (using the "delegate" keyword). Whereas "event" is used in the context of declaring a

member variable, not declaring a type.

I don't know why events can only be fired by class that declare the event. In most cases you end up adding a

method (usually with the On* prefix) to get around this restriction. I'll try to find more about the reason for

this design.

Let me know if you find that information before I do.

Posted by: Dumky at October 3, 2003 11:30 PM

Thanks for the article - it was very useful.

An example of the relevance of the add/remove accessors on events is when you use them on remoted

objects. (eg. Client connects to remoted object on a server and subscribes to state change events). If a

remoted object exposes an event, but no delegates have been registered to the event, then there is no need to

source the information needed to raise the event (or raise the event for that matter). There may be a high

cost in starting/running the process that sources the event information. Adding event accessors allows you to

hook the introduction/removal of the delegate.

This is also true of non-remoted objects.

Page 7 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 8: C# Delegates Event Whitepaper

Posted by: tingeyp at October 15, 2003 03:26 AM

Useful article, much appreciated!

I have a quick question about derived classes raising parent class events. What is the rationale for not

allowing a subclass to raise a parent class's events. I can obviously understand classes outside the hierarchy

not being able to, but subclasses? It just isn't clear.

Posted by: skarab at November 10, 2003 01:29 PM

Ignore my last comment. I didn't read others' comments before posting. Shame on me!

Posted by: skarab at November 10, 2003 01:46 PM

No problem. I just updated the post with the rationale that makes the most sense so far.

I'm also trying to get an explanation from somebody on the CLR or C# team.

Posted by: Dumky at November 10, 2003 07:54 PM

Great Efforts..I really appriciate the examples and explanation.

Posted by: Rafi at February 15, 2004 08:20 PM

Excellent article. Thanks much.

Posted by: Rocky at March 25, 2004 12:31 PM

Nice article. I did not find this information anywhere else. Thanks..

Posted by: Rajeev at May 1, 2004 03:53 PM

A cleaner solution now at http://blogs.msdn.com/jaybaz_ms/archive/2004/06/17/158636.aspx

Posted by: jaybaz [MS] at June 17, 2004 02:28 PM

very good and drilled down.

Posted by: Ali Asghar Ahmed at July 4, 2004 01:12 AM

Thanks a lot!

I never was exactly sure what "event" did, even after reading all about it in "Inside C#". The only purpose I

thought it served was to let the VS.NET IDE list it as an available "Event" for the class! (Which is also an

important side-effect.)

Page 8 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 9: C# Delegates Event Whitepaper

Your explanation was well appreciated

Posted by: Robert at August 19, 2004 03:06 PM

I have a basic question and i am new to C#.

Is there anyway, i can shadow/hide a Parent Controls event.

I am trying to do this

public new event EventHandler SelectedIndexChanged (object sender, SelectedIndexChangedEventArgs e);

Is this a right approach?

I like to hide the regular event and write my own ? Thanks

Posted by: Bob at September 2, 2004 01:00 PM

Hi,

Great post, The restriction on the events that "Invoking an event can only be done from within the class that

declared the event" is not easily understood, may it is to place more emphasis on the class which defines the

event, for it to decide and fire the event.

I have given a example stating this difference between events and delegates at:

http://narasimhagm.blogspot.com/2004/11/c-events-and-delegates.html

Regards

Narasimha G. M.

Posted by: Narasimha G. M. at January 1, 2005 01:46 AM

This is a great article . Thanks

Posted by: Vijaya at January 6, 2005 10:08 PM

Great Article. Exactly what i needed.

Posted by: Ganesh at January 7, 2005 01:13 AM

Great Work - Found it very Useful.

Posted by: Gautham Chuliyill at January 17, 2005 11:58 PM

Thanks a lot.

You helped me a lot.

Posted by: Fernando Miranda at January 19, 2005 10:52 AM

Page 9 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 10: C# Delegates Event Whitepaper

Above, you mention a race condition

if (Click != null)

Click(arg1, arg2);

This is interesting. You never had this problem in Java. You could follow the example

here....http://java.sun.com/j2se/1.5.0/docs/api/index.html

and did not need to do any synchronization. Being able to do stuff without synchronization sometimes helps

performance problems that were caused by contention. I guess I could always fall back to the way Java does

listeners in C#.

Posted by: Dean Hiller at March 31, 2005 11:33 AM

Dean, the problem is that events in C# are not simply listeners, they are listener collections.

What if the collection is modified as it gets iterated over for sending the events?

In Java you would still have a problem if somebody (ie another thread) removed the listener object between

the null check and the actual call.

Posted by: Julien Couvreur at March 31, 2005 11:37 AM

Very useful - thanks much.

Posted by: netshade at April 21, 2005 11:23 AM

What a post. Beauty !

But I am somewhat puzzled by you remark on the restriction of the delegate's signature you can apply the

events keyword upon. Testing it I did not find any problems in using different signatures. And when it comes

to COM events, where you really need the event keyword, the System.EventHandler 's signature does not

make any sense.

What am I missing ?

Posted by: Peter van Ooijen at August 31, 2005 12:40 PM

Hey Peter,

Thanks.

Regarding the signature restriction on events in .Net, I'm actually

not sure. I've never seen that restriction in action. It might only

apply for CLS-Compliant code.

Re-reading the MSDN doc on the topic, it's still not quite clear:

".NET Framework Guidelines

Although the C# language allows events to use any delegate type, the

.NET Framework has some stricter guidelines on the delegate types that

Page 10 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 11: C# Delegates Event Whitepaper

should be used for events. If you intend for your component to be used

with the .NET Framework, you probably will want to follow these

guidelines.

The .NET Framework guidelines indicate that the delegate type used for

an event should take two parameters, an "object source" parameter

indicating the source of the event, and an "e" parameter that

encapsulates any additional information about the event. The type of

the "e" parameter should derive from the EventArgs class. For events

that do not use any additional information, the .NET Framework has

already defined an appropriate delegate type: EventHandler."

(from http://msdn.microsoft.com/library/default.asp?url=/library/en-

us/csref/html/vcwlkEventsTutorial.asp)

Let me know if you find any clear explanation.

Posted by: Julien Couvreur at September 2, 2005 06:07 PM

I read some post comment on events & delegates but Still I don't clear the concept of events &

delegates.Please help me.

Posted by: PRASHANT at September 22, 2005 10:23 PM

Hey Prashant,

You should be able to find a lot of info online. Events are just some restrictions on top of delegates, so you

should focus on understanding delegates first.

Delegates are essentially method pointers. Very useful for callback scenarios, ie. I call a component

asynchronously passing in a callback method, the call returns and, later, the callback gets called back.

It's also used a lot in winforms code, for notifications: this button was clicked, this window was closed,...

Posted by: Julien Couvreur at September 23, 2005 07:31 PM

Hey,

thanks a lot for this article. It was of a great help for me.

Posted by: Brijesh Choubey at September 29, 2005 03:06 AM

I was searching for exactly this.

One more difference wrt VisualStudio (although doesnt have anything to do with language but makes

difference while desiging applications),

When you mark something "event", the designer displays it in event-property window.

Posted by: Sandeep at October 27, 2005 05:37 PM

Page 11 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 12: C# Delegates Event Whitepaper

Okay, so this is quite a few months later, but:

if you use a delegate directly, an outside object can invoke it when really, you just want the owning object to

do the invoking. With the event keyword modifier, you can no longer call invoke on it.

Hope that helps anyone who stumbles upon this.

Posted by: Mr. Raybell at March 10, 2006 04:28 PM

Does the code you suggest (well, actually, other people suggest) really fix the race condition problem?

It seems to me that the race condition has not been fixed by this adjustment. Aren’t you just ensuring you

"win the race" by copying out the event to temporary variable? You are only guaranteeing that collection you

have is not empty when you invoke it, but you have not guaranteed that the subscriber is still valid. Let me

give you an example.

Suppose I create a new dialog box and in that dialog box I subscribe to your event. In my dialog box, I choose

to subscribe to your event. The user clicks OK on my dialog box, and your thread, at that moment, decides to

fire. It copies the event list, and checks to see if it is null. Now my thread continues to run. In my main form,

I destroy the dialog box, removing my hander from the real event (not the copy), and get ready to call

gc.collect(), but just before I do, your thread keeps running. My object is “gone” enough to not work

properly, but not “gone” enough to be recognized as non-existent by the gc. It has destroyed all of its internal

variables, and will crash if called because the code will throw exceptions due to the variables being no longer

initialized. I am not expecting a call any more. But your thread is just now invoking the event with its saved

copy.

What happens? Does the event just not get invoked for some reason? I can’t see why that would be… If it

does get invoked, bad stuff for sure will happen.

Unless there is some behind-the-scene reason why the handler will not actually be called -- how can it know

this if it doesn’t know the object has been gc’ed? – bad stuff will happen. All the copy has done is make the

race condition more complicated, more difficult to catch, it hasn’t eliminated it.

It seems the only way to eliminate the problem is either 1) to put some kind of lock on the event variable and

get that lock before triggering the event (the event handler can still remove itself, just ignore the lock. If

you’ve already been activated, there’s no worry that you’ll mess stuff up, assuming the code behind events is

properly written…) or 2) to never let more than one thread deal with any given event/handler group.

I suspect the authors intentionally assumed you would not attempt to use events with multiple threads in

this way.

I’m not certain I’m right, but this certainly bothers me!

Posted by: Chiem at April 11, 2006 10:59 AM

Perfect! I've been reading up on delegates and events and couldn't figure out why we needed events at all.

This answered my question exactly!

Thanks!

Page 12 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 13: C# Delegates Event Whitepaper

Posted by: ian at July 24, 2006 03:41 PM

It really helped me in finding some differences.

Posted by: Arif Sarwar at August 7, 2006 12:55 PM

Great article!

You write very well on a difficult\tricky subject.

Thank you!

Posted by: Kalan at August 14, 2006 03:39 PM

figure3 in the following article explains why the Event invocation restriction

http://msdn.microsoft.com/msdnmag/issues/01/08/net/

Posted by: Dean at August 23, 2006 11:37 AM

Trackbacks

More details on events vs. delegates

Excerpt:

Weblog: ISerializable

Tracked: March 29, 2004 10:58 AM

The dark side of C# Delegates

Excerpt: The dark side of C# Delegates

Weblog: dudu

Tracked: May 23, 2004 04:00 AM

re: Events versus Delegates

Excerpt:

Weblog: Dan Vallejo's WebLog

Tracked: May 23, 2004 08:53 AM

C# Events vs. Delegates, Race Conditions and testing for Null...

Excerpt:

Weblog: Eladio

Tracked: July 27, 2005 06:20 AM

C# Events vs. Delegates, Race Conditions and testing for Null...

Excerpt:

Weblog: Eladio

Tracked: July 30, 2005 12:56 PM

Page 13 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html

Page 14: C# Delegates Event Whitepaper

The C# event keyword is an access modifier for delegate members

Excerpt: Recently I had trouble getting COM events to work in a COM automation server written in C#. A visitor's...

Weblog: Peter's Gekko

Tracked: September 1, 2005 08:54 AM

C# Events vs. Delegates, Race Conditions and testing for Null...

Excerpt: Here is an interesting article on the differences between Events and Delegates... The author gets...

Weblog: Eladio Martin

Tracked: October 18, 2005 05:53 PM

Comments are closed. You can contact me by email.

R E C E N T E N T R I E S

All entries (262)

Better async programming in .Net 5.0

Action, preferences, value

Fresh breeze on climate debate

On-the-fly book scanning

State and education

Live Geometry screencast

Wired Science TV show

Expectations and accountability in Economics

Science of human action

Reactive programming in javascript and C#

Google Wave

Reading facial expressions

Google Android architecture

MSDN light

Kindle 2 review

Orange Juice

Better software for multitasking

Amazon Kindle review

New president and the economy

Ubiquity command: proxy-set

Page 14 of 14Curiosity is bliss: C# events vs. delegates

5/12/2011http://blog.monstuff.com/archives/000040.html