diff --git a/src/Avalonia.Base/PropertyStore/ValueStore.cs b/src/Avalonia.Base/PropertyStore/ValueStore.cs index a90bb4eb73..4db4b141f1 100644 --- a/src/Avalonia.Base/PropertyStore/ValueStore.cs +++ b/src/Avalonia.Base/PropertyStore/ValueStore.cs @@ -528,9 +528,8 @@ namespace Avalonia.PropertyStore private void InsertFrame(IValueFrame frame) { Debug.Assert(!_frames.Contains(frame)); - var index = _frames.BinarySearch(frame, FrameInsertionComparer.Instance); - if (index < 0) - index = ~index; + + var index = BinarySearchFrame(frame.Priority); _frames.Insert(index, frame); ++_frameGeneration; frame.SetOwner(this); @@ -569,15 +568,12 @@ namespace Avalonia.PropertyStore { Debug.Assert(priority != BindingPriority.LocalValue); - // TODO: Binary search? - for (var i = _frames.Count - 1; i >= 0; --i) - { - var frame = _frames[i]; - if (frame is ImmediateValueFrame immediate && !immediate.Contains(property)) - return immediate; - if (frame.Priority > priority) - break; - } + var index = BinarySearchFrame(priority); + + if (index > 0 && _frames[index - 1] is ImmediateValueFrame f && + f.Priority == priority && + !f.Contains(property)) + return f; var result = new ImmediateValueFrame(priority); InsertFrame(result); @@ -915,14 +911,28 @@ namespace Avalonia.PropertyStore } } - private class FrameInsertionComparer : IComparer + private int BinarySearchFrame(BindingPriority priority) { - public static readonly FrameInsertionComparer Instance = new FrameInsertionComparer(); - public int Compare(IValueFrame? x, IValueFrame? y) + var lo = 0; + var hi = _frames.Count - 1; + + // Binary search insertion point. + while (lo <= hi) { - var result = y!.Priority - x!.Priority; - return result != 0 ? result : -1; + var i = lo + ((hi - lo) >> 1); + var order = priority - _frames[i].Priority; + + if (order <= 0) + { + lo = i + 1; + } + else + { + hi = i - 1; + } } + + return lo; } private readonly struct OldNewValue