Skip to content

Commit

Permalink
perf: Don't use multicast delegates for DependencyObjectCollection.Ve…
Browse files Browse the repository at this point in the history
…ctorChanged

This change avoids the high cost of multicast delegates, particularly on mono-AOT environments. We also do not need the thread safety guarantees.
  • Loading branch information
jeromelaban committed Nov 25, 2024
1 parent 9883391 commit 0544fb5
Showing 1 changed file with 19 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/Uno.UI/UI/Xaml/DependencyObjectCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ public partial class DependencyObjectCollectionBase : DependencyObject
public partial class DependencyObjectCollection<T> : DependencyObjectCollectionBase, IList<T>, IEnumerable<T>, IEnumerable, IObservableVector<T>
where T : DependencyObject
{
public event VectorChangedEventHandler<T> VectorChanged;
// Explicit handlers list to avoid the cost of multicast delegates handling
private List<VectorChangedEventHandler<T>> _vectorChangedHandlers;

public event VectorChangedEventHandler<T> VectorChanged
{
add => (_vectorChangedHandlers ??= new()).Add(value);
remove => (_vectorChangedHandlers ??= new()).Remove(value);
}

private readonly List<T> _list = new List<T>();

Expand Down Expand Up @@ -205,7 +212,17 @@ internal List<T>.Enumerator GetEnumeratorFast()
=> _list.GetEnumerator();

private void RaiseVectorChanged(CollectionChange change, int index)
=> VectorChanged?.Invoke(this, new VectorChangedEventArgs(change, (uint)index));
{
if (_vectorChangedHandlers is not null)
{
var args = new VectorChangedEventArgs(change, (uint)index);

foreach (var handler in _vectorChangedHandlers)
{
handler.Invoke(this, args);
}
}
}

private protected virtual void OnAdded(T d)
{
Expand Down

0 comments on commit 0544fb5

Please sign in to comment.