HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Type-Safe Event System

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
typesystemsafeevent

Problem

I have recently started writing C# from a strong JavaScript background, and found myself wanting to do something I do all the time in JavaScript: events.

Since I have a type system at my disposal, I figured I'd make use of it and make the event system type safe.

A quick note on existing options:

C#'s built-in event library didn't really appeal to me - for one, I don't really like the syntax (eg listeners += callback), but more than that, I wanted type-safety in the callbacks. (ie, I want the callback to be something like Action, not public void delegate SomeEventHandler(object sender, EventArgs args)).

Unity's built-in UnityEvent looks pretty good, but these aren't collected and managed in any way. I decided to roll my own Events to go with my EventManager, but I think I could adapt it to use UnityEvent fairly easily.

The code compiles and works, but I am wondering if there's a more elegant solution - or even if there's just a way I could reduce the boilerplate in my own solution. (Generics seem to cause most if not all of the boilerplate, but I didn't see a better way to get type-safety in callbacks.)

Here's how it is used:

using EventSystem;
// create SomeEvent - uses a class stub, not sure how I feel about that
public class SomeEvent : BasicEvent { }

// listen to it somewhere else in the codebase...
EventManager.On((param) => / ... /);
// and trigger it somewhere different still...
EventManager.Trigger(someParameter);


Here's how it is structured:

  • namespace EventSystem



  • EventManager.cs, a static class that can be used to listen to / detach from and trigger events



  • EventBehaviour.cs, an abstract class that "registers" an event with the EventManager using Unity's Awake () { ... } - basically glue between the event system and Unity



  • IEventListener.cs, generic interfaces that define a type-safe listener, and have extension methods for implementing listener Invoke methods for any of the defined generics



  • `BasicListener.c

Solution

C# events are type-safe. The common (and recommended) pattern is to use EventHandler, where T is a custom type deriving from EventArgs, containing the data of the event. You should use this pattern if possible, especially if you're writing a library that will be used by third parties.

The problems that I can see in this pattern are:

  • The sender parameter is always object. It's either not useful (because you can access the object directly thanks to lambdas) or requires casting.



  • The eventArgs parameter should derive from EventArgs. This means you need to litter your code with lots of types that derive from EventArgs, even if the data of the event is just a single value.



If you're set on not using this pattern, I think you should still use event, just not with EventHandler.

The simplest version of that is just:

public event Action SomeEvent;

Code Snippets

public event Action<SomeParameter> SomeEvent;

Context

StackExchange Code Review Q#120664, answer score: 11

Revisions (0)

No revisions yet.