Java's rather neat 'inline implementations of an interface' / 'inline class definitions' (which you've illustrated above) aren't a part of C#.
You could go ahead and implement listener interfaces/classes and pass them into objects, which is in effect the same thing - however, this can get quite verbose very quickly, and oftentimes you really only want to provide a single callback anyway.
C# has two helpful tools that make life a lot easier:
- Delegates
- Events
Delegates
It makes sense to understand Delegates before looking at Events. A Delegate is a neat way to pass a method around as a variable or parameter.
You can define Delegate types (if you wish):
public delegate void AMethodThatHandlesAnInteger(int theInt);
And then use them as parameters for methods:
public void doStuffAndThenCallADelegate(AMethodThatHandlesAnInteger theDelegate)
{
...
theDelegate(4);
}
Or, more often than not, it's easier to use one of the pre-defined delegates that already exist:
public void doStuffAndThenCallADelegate(Action<int> theDelegate)
{
...
theDelegate(4);
}
Delegates can be generic - and this makes them a very powerful tool.
There are a number of delegates defined by the framework, (as listed by the handy Q&A linked to). I often find myself using Action
(void method, takes no parameters), and Action<Something>
(void method, takes a single parameter) in simple cases.
Func<Something,Else>
allows a return type, and it gets more interesting from there! Actions and Funcs allow 0-4 parameters (not including the return type for Func).
Events
Whilst it's possible to build your own pattern to monitor object changes using delegates, C# goes one step further and provides ready-made events for you...
Events are an extremely convenient way for an object to collate 'handler' delegate methods, and then to be able to call them all with a set of parameters.
First define the delegate type for the 'handler' methods:
public delegate void StuffHappenedHandler(int stuffs, string summary);
Then by defining a public event, you create a reachable field for registration/deregistration of delegates. I sometimes prefix my events with 'On' - it's a matter for code styling:
public event StuffHappenedHandler OnStuff;
An object that wishes to monitor this event needs a method that matches the StuffHappenedHandler
delegate type signature:
public void MonitoredObjectStuffHandler(int howMany, string summary)
{
...
}
Now it can register that method with the OnStuff
event:
monitoredObject.OnStuff += ObjectStuffHandler;
To deregister a delegate method from the event, it's just as simple:
monitoredObject.OnStuff -= ObjectStuffHandler;
When it comes to notifying objects that might be listening, it's important to check for a null event. The event will be null if there's nothing registered:
if (OnStuff != null)
OnStuff(4, "four things");