diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj index 887d3ff9bd..46e24aa15a 100644 --- a/src/Avalonia.Base/Avalonia.Base.csproj +++ b/src/Avalonia.Base/Avalonia.Base.csproj @@ -118,6 +118,7 @@ + diff --git a/src/Avalonia.Base/PriorityValue.cs b/src/Avalonia.Base/PriorityValue.cs index a7eb4465b3..3f4b405de9 100644 --- a/src/Avalonia.Base/PriorityValue.cs +++ b/src/Avalonia.Base/PriorityValue.cs @@ -28,7 +28,7 @@ namespace Avalonia { private readonly IPriorityValueOwner _owner; private readonly Type _valueType; - private readonly Dictionary _levels = new Dictionary(); + private readonly SingleOrDictionary _levels = new SingleOrDictionary(); private object _value; private readonly Func _validate; diff --git a/src/Avalonia.Base/Utilities/SingleOrDictionary.cs b/src/Avalonia.Base/Utilities/SingleOrDictionary.cs new file mode 100644 index 0000000000..fd984d758a --- /dev/null +++ b/src/Avalonia.Base/Utilities/SingleOrDictionary.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Avalonia.Utilities +{ + /// + /// Stores either a single key value pair or constructs a dictionary when more than one value is stored. + /// + /// The type of the key. + /// The type of the value. + public class SingleOrDictionary : IEnumerable> + { + private KeyValuePair? _singleValue; + private Dictionary dictionary; + + public void Add(TKey key, TValue value) + { + if (_singleValue != null) + { + dictionary = new Dictionary(); + ((ICollection>)dictionary).Add(_singleValue.Value); + _singleValue = null; + } + + if (dictionary != null) + { + dictionary.Add(key, value); + } + else + { + _singleValue = new KeyValuePair(key, value); + } + } + + public bool TryGetValue(TKey key, out TValue value) + { + if (dictionary == null) + { + if (!_singleValue.HasValue || !_singleValue.Value.Key.Equals(key)) + { + value = default(TValue); + return false; + } + else + { + value = _singleValue.Value.Value; + return true; + } + } + else + { + return dictionary.TryGetValue(key, out value); + } + } + + public IEnumerator> GetEnumerator() + { + if (dictionary == null) + { + if (_singleValue.HasValue) + { + return new SingleEnumerator>(_singleValue.Value); + } + } + else + { + return dictionary.GetEnumerator(); + } + return Enumerable.Empty>().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public IEnumerable Values + { + get + { + if(dictionary == null) + { + if (_singleValue.HasValue) + { + return new[] { _singleValue.Value.Value }; + } + } + else + { + return dictionary.Values; + } + return Enumerable.Empty(); + } + } + + private class SingleEnumerator : IEnumerator + { + private T value; + private int index = -1; + + public SingleEnumerator(T value) + { + this.value = value; + } + + public T Current + { + get + { + if (index == 0) + { + return value; + } + else + { + throw new InvalidOperationException(); + } + } + } + + object IEnumerator.Current => Current; + + public void Dispose() + { + } + + public bool MoveNext() + { + index++; + return index < 1; + } + + public void Reset() + { + index = -1; + } + } + + } +}