diff --git a/src/BizHawk.Common/CustomCollections.cs b/src/BizHawk.Common/CustomCollections.cs index 8f0eec5c63..2df9d75dfd 100644 --- a/src/BizHawk.Common/CustomCollections.cs +++ b/src/BizHawk.Common/CustomCollections.cs @@ -4,17 +4,28 @@ using System.Linq; namespace BizHawk.Common { - public class SortedList : IList + public class SortedList : IList, IList, IReadOnlyList where T : IComparable { private const string ERR_MSG_OUT_OF_ORDER = "setting/inserting elements must preserve ordering"; + private const string ERR_MSG_WRONG_TYPE = "wrong type"; + protected readonly List _list; public virtual int Count => _list.Count; + bool IList.IsFixedSize + => false; + public virtual bool IsReadOnly { get; } = false; + bool ICollection.IsSynchronized + => false; + + object ICollection.SyncRoot + => this; + protected SortedList(List wrapped) => _list = wrapped; @@ -46,20 +57,43 @@ namespace BizHawk.Common } } + object? IList.this[int index] + { + get => _list[index]; + set + { + if (value is not T value1) throw new ArgumentException(paramName: nameof(value), message: ERR_MSG_WRONG_TYPE); + this[index] = value1; + } + } + public virtual void Add(T item) { var i = _list.BinarySearch(item); _list.Insert(i < 0 ? ~i : i, item); } + int IList.Add(object? item) + { + if (item is not T item1) throw new ArgumentException(paramName: nameof(item), message: ERR_MSG_WRONG_TYPE); + Add(item1); + return IndexOf(item1); + } + public virtual int BinarySearch(T item) => _list.BinarySearch(item); public virtual void Clear() => _list.Clear(); public virtual bool Contains(T item) => !(_list.BinarySearch(item) < 0); // can't use `!= -1`, BinarySearch can return multiple negative values + bool IList.Contains(object? item) + => item is T item1 && Contains(item1); + public virtual void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); + void ICollection.CopyTo(Array array, int arrayIndex) + => ((ICollection) _list).CopyTo(array, arrayIndex); + public T FirstOrDefault() => _list.Count is 0 ? default! : _list[0]; @@ -79,6 +113,11 @@ namespace BizHawk.Common return i < 0 ? -1 : i; } + int IList.IndexOf(object? item) + => item is T item1 + ? IndexOf(item1) + : throw new ArgumentException(paramName: nameof(item), message: ERR_MSG_WRONG_TYPE); + public virtual void Insert(int index, T item) { // allowing appends per `IList` docs @@ -94,6 +133,12 @@ namespace BizHawk.Common else throw new NotSupportedException(ERR_MSG_OUT_OF_ORDER); } + void IList.Insert(int index, object? item) + { + if (item is not T item1) throw new ArgumentException(paramName: nameof(item), message: ERR_MSG_WRONG_TYPE); + Insert(index, item1); + } + public T LastOrDefault() => _list.Count is 0 ? default! : _list[_list.Count - 1]; @@ -109,6 +154,12 @@ namespace BizHawk.Common #endif } + void IList.Remove(object? item) + { + if (item is not T item1) throw new ArgumentException(paramName: nameof(item), message: ERR_MSG_WRONG_TYPE); + _ = Remove(item1); + } + public virtual int RemoveAll(Predicate match) => _list.RemoveAll(match);