Essentials: Events vs Delegates

Created on 30 Mar 2018  路  7Comments  路  Source: xamarin/Essentials

I have been looking at various APIs and noticed that there is a difference in the way event streams are implemented:

Cancellable Delegates

class GPS {
    void Start(Precision precision, CancellationToken token, Action<Location> onUpdate);
}

This would be used in code like this:

// in order to stop the events
var cts = new CancellationTokenSource();

// to start the events
GPS.Start(Precision.High, cts.Token, location => {
    // update the UI or something
});

// to stop the events
cts.Cancel();

Events

class GPS {
    event Action<Location> Updated;
    // OR
    event EventHandler<LocationUpdatedEventArgs> Updated;
    void Start(Precision precision);
    void Stop();
}

This would be used in code like this:

// in order to get events
GPS.Updated += (location) => {
    // update the UI or something
});
// OR
GPS.Updated += (sender, e) => {
    var location = e.Location
    // update the UI or something
});

// to start the events
GPS.Start(Precision.High);

// to stop the events
GPS.Start();

Discussion Points

  • Do .NET developers prefer events or delegates?
    .NET is very much an event based system, so many users may be familiar with that approach.
  • Is there a performance overhead/difference between the different methods?
  • *What happens if the app needs to track the same event in different places, but at the same time?
    An example is that one GPS may update two independent parts of the app that are not talking to each other. Two separate ViewModels may talk to the same GPS by each attaching to the event stream. In this case events are better.
  • What happens if the app needs to track the same event, but with different criteria?
    An example is that the app may want to track a coarse location to update a news feed for events in the area, but possibly at the same time track a fine location for the onscreen map. In this case, the events are better.
  • What happens if the physical hardware only allows for a single event stream?
    This may be something that the GPS can only return events at single rate, so it will be impossible to have a coarse location and a fine location from the same hardware.
  • Do people really want to create a CancellationTokenSource and then start the event?
  • Do people really want to have to attach an event and then call start?
  • How does this integrate with event stream frameworks (such as Rx)?
question

All 7 comments

I think we just design Events and then Rx can create observables automatically.

Will be changing compass over.

1.) Have Start/Stop if they need configuration
2.) If no configuration: Auto start/stop when events are added/removed

We could always combine the approaches to make our lives harder:

class GPS {
    event EventHandler<LocationUpdatedEventArgs> Updated;
    void Start(Precision precision) {
        // start the hardware
    }
    void Start(Precision precision, CancellationToken token, Action<Location> onUpdate) {
        void OnUpdateReceived(object sender, LocationUpdatedEventArgs e) {
            onUpdate(e.Location);
        }
        token.Register(() => Updated -= OnUpdateReceived);
        Updated += OnUpdateReceived;
        Start();
    }
}

Although this will be confusion, I start my delegate, but then all the other event handlers start???

Let's just stick with one way of doing it.

I think the interesting part maybe is the "Action" option or not....

I think we should use Action<T> or rather a custom delegate delegate void UpdatedEventHandler(LocationUpdatedEventArgs e); without the sender be cause we are static.

UWP has a few with sender (such as on DisplayInfo) but this is weird as sender is always null...

Using generic actions is maybe performance overhead that we don't need? Then again, we will have loads of delegates... And then again (again) .NET has always used EventHandler so we may want to be consistent... Aargh!

Yeah, this is what I do:

public delegate void MagnetometerChangedEventHandler(MagnetometerChangedEventArgs e);

usage:

Magnetometer.ReadingChanged += Magnetometer_ReadingChanged;


private void Magnetometer_ReadingChanged(MagnetometerChangedEventArgs e)
 {
}

I think it is the correct move.

I agree with no sender, which i think is what you did originally too for orientation changes.

Yeah sender is not useful here

Was this page helpful?
0 / 5 - 0 ratings