Are delegates the reason we have C#?
This may be ancient news, but I just came across an article that strongly implied that the reason .NET came about was because Sun didn't like Microsoft's addition of delegates to J++. That surely is a condensation of events, but it's certainly an interesting yarn.
I got into this whole subject because I needed an object to subscribe to the state change of another object in my java project. And I didn't want to create a tight coupling between otherwise unrelated objects. In C#, I would have created an event for the state change and have the second object subscribe to it. Done.
Alas, I'm in java and don't have delegates, e.g. no events in the way i'm used to. I remembered dealing with creating lots of anonymous inner classes during some long ago experiences with swing programming, which I always found to be less than transparent in presentation. So I figured I'd do some digging to see how delegation and events should be handled in java. I don't like seeing getFoo()/setFoo()
from someone not used to C# properties, and I don't want to subject someone else to my C#-ing of java code in return.
I started googling java, delegates and inner classes and came across a plethora of interesting articles, including the obligatory C# is better better than java because it has delegates and java kicks C#'s ass because isn't littered with atrocious syntactic sugar like delegates when inner classes will do variety. Of these, the most entertaining was a rather testy condemnation of delegates in J++ in the form of a white paper on Sun's site. Considering the stance Sun has taken over the years on java, i.e. binding the language, runtime and philosophy into a single indivisible unit, having MS try subvert the language with what to many looks like a procedural programming throwback certainly could have been a significant motivator for the lawsuit that revoked Microsoft's java license. Looking at C# and the CLR, Microsoft obviously saw a lot of things it liked in the java language and the jvm. So the result that .NET came about because Sun rejected delegates doesn't seem too far fetched and my favorite version of the story so far.
Now, back to the problem at hand, how does one do delegation in java and the answer does appear to be with inner classes functioning as callbacks. This certainly does the trick. But that's a bunch of code and interfaces to create which in the end doesn't improve the readability of the code. As an illustration, here is the C# code and the java code I created to get the same effect. Note: I didn't need the extra information that C# events provide, i.e. the event source and event arguments, so I left them out of the java version to keep the code more concise. I also didn't do any checking if there are subscribers, etc -- read: this is an illustration not production code :)
Publisher
/ C# Publisher
public class Publisher
{
// create the event, which implicitly gives us add/delete subscribers
public event EventHandler someAction;
public void DoAction()
{
Console.WriteLine("Start action");
//implictly call all subscribers
someAction(this, EventArgs.Empty);
Console.WriteLine("End action");
}
}
// java Publisher
public class Publisher {
private List<EventHandler> subscribers = new ArrayList<EventHandler>();
public void subscribeToAction(EventHandler notifier)
{
subscribers.add(notifier);
}
public void doAction()
{
System.out.println("Start action");
for( EventHandler subscriber : subscribers ) {
subscriber.handle(this);
}
System.out.println("End action");
}
}
Subscriber
//C# Subscriber
public class Subscriber
{
private string name;
public Subscriber(string name)
{
this.name = name;
}
public void AttachToPublisher(Publisher publisher)
{
// subscribe to the event. This creates a closure for this particular
// instance of Subscriber.
publisher.someAction += new EventHandler(RespondToAction);
}
void RespondToAction(object sender, EventArgs e)
{
Console.WriteLine("Responding to action for '" + name + "'");
}
}
// java Subscriber
public class Subscriber {
private String name;
public Subscriber(String name) {
this.name = name;
}
public void attachToPublisher(Publisher publisher) {
// create a new anonymouse instance of the EventHandler
// as a closure for this instance of Subscriber
publisher.subscribeToAction(new EventHandler() {
public void handle(Publisher publisher) {
respondToAction();
}
}
);
}
private void respondToAction() {
System.out.println("Responding to action for '" + name + "'");
}
}
EventHandler
In C# this is just built in plumbing. In java we create a simple interface that our anonymous inner class will implement:
Now we exercise the code:
Publisher p = new Publisher();
Subscriber s1 = new Subscriber("abc");
Subscriber s2 = new Subscriber("xyz");
s1.AttachToPublisher(p);
s2.AttachToPublisher(p);
p.DoAction();
The java code is virtually identical just with different casing for code style and both produce this output:
Now add lost of different events and unsubscribing of events, plus more complex EventHandlers and the amount of code you end up writing quickly becomes significant. If there is one thing object oriented programming encourages us to do is to take repetitive code patterns and formulate reusable objects. Plenty of people in the java community have created delegate-like helpers that make delegation easier to read and maintain than simple inner classes, my favorite so far being Alex Winston's strongly typed approach.
So are delegates just syntactic sugar or a throw-back to procedural coding? For those with only a cursory understanding of delegates, they do just look like function pointers, like C, or at best, type-safe function pointers. But just like inner classes they create instance specific closures, plus they throw in functionality for handling multi-casting and handling synchronous and asynchronous invocation of the closure. I, at least, think delegates as a first-class citizen of the runtime make life easier, improve readability and do not detract from the object oriented nature of the surrounding code.