Implement remaining `IList<T>` methods on `SortedList<T>`
This commit is contained in:
parent
33571d4cd3
commit
5a236fdbee
|
@ -3,9 +3,11 @@ using System.Collections.Generic;
|
|||
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
public class SortedList<T> : ICollection<T>
|
||||
public class SortedList<T> : IList<T>
|
||||
where T : IComparable<T>
|
||||
{
|
||||
private const string ERR_MSG_OUT_OF_ORDER = "setting/inserting elements must preserve ordering";
|
||||
|
||||
protected readonly List<T> _list;
|
||||
|
||||
public virtual int Count => _list.Count;
|
||||
|
@ -20,7 +22,24 @@ namespace BizHawk.Common
|
|||
_list.Sort();
|
||||
}
|
||||
|
||||
public virtual T this[int index] => _list[index];
|
||||
public virtual T this[int index]
|
||||
{
|
||||
get => _list[index];
|
||||
set
|
||||
{
|
||||
// NOT allowing appends, to match BCL `List<T>`
|
||||
if (index < 0 || Count <= index) throw new ArgumentOutOfRangeException(paramName: nameof(index), index, message: $"index must be in 0..<{Count}");
|
||||
if (Count is 0)
|
||||
{
|
||||
_list.Add(value);
|
||||
return;
|
||||
}
|
||||
var willBeGeqPrevious = index is 0 || value.CompareTo(_list[index - 1]) >= 0;
|
||||
var willBeLeqFollowing = index == Count - 1 || _list[index + 1].CompareTo(value) >= 0;
|
||||
if (willBeGeqPrevious && willBeLeqFollowing) _list[index] = value;
|
||||
else throw new NotSupportedException(ERR_MSG_OUT_OF_ORDER);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Add(T item)
|
||||
{
|
||||
|
@ -55,6 +74,21 @@ namespace BizHawk.Common
|
|||
return i < 0 ? -1 : i;
|
||||
}
|
||||
|
||||
public virtual void Insert(int index, T item)
|
||||
{
|
||||
// allowing appends per `IList<T>` docs
|
||||
if (index < 0 || Count < index) throw new ArgumentOutOfRangeException(paramName: nameof(index), index, message: $"index must be in 0..{Count}");
|
||||
if (Count is 0)
|
||||
{
|
||||
_list.Add(item);
|
||||
return;
|
||||
}
|
||||
var willBeGeqPrevious = index is 0 || item.CompareTo(_list[index - 1]) >= 0;
|
||||
var willBeLeqFollowing = index >= Count - 1 || _list[index].CompareTo(item) >= 0;
|
||||
if (willBeGeqPrevious && willBeLeqFollowing) _list.Insert(index, item);
|
||||
else throw new NotSupportedException(ERR_MSG_OUT_OF_ORDER);
|
||||
}
|
||||
|
||||
public T LastOrDefault()
|
||||
=> _list.Count is 0 ? default! : _list[_list.Count - 1];
|
||||
|
||||
|
|
|
@ -26,6 +26,23 @@ namespace BizHawk.Tests.Common.CustomCollections
|
|||
Assert.IsTrue(list.Contains(11)); // `Contains` when `BinarySearch` returns non-negative
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSortedListInsert()
|
||||
{
|
||||
SortedList<int> list = new([ 1, 4, 7 ]);
|
||||
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 3, item: 0), "setting [^0] (appending) out-of-order should throw");
|
||||
list.Insert(index: 3, item: 10);
|
||||
Assert.IsTrue(list.SequenceEqual([ 1, 4, 7, 10 ]), "expecting [ 1, 4, 7, 10 ]");
|
||||
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 3, item: 0), "setting [^1] out-of-order should throw");
|
||||
list.Insert(index: 3, item: 9);
|
||||
Assert.IsTrue(list.SequenceEqual([ 1, 4, 7, 9, 10 ]), "expecting [ 1, 4, 7, 9, 10 ]");
|
||||
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 1, item: 9), "setting [1] out-of-order should throw");
|
||||
list.Insert(index: 1, item: 3);
|
||||
Assert.IsTrue(list.SequenceEqual([ 1, 3, 4, 7, 9, 10 ]), "expecting [ 1, 3, 4, 7, 9, 10 ]");
|
||||
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 0, item: 9), "setting [0] out-of-order should throw");
|
||||
list.Insert(index: 0, item: 0);
|
||||
Assert.IsTrue(list.SequenceEqual([ 0, 1, 3, 4, 7, 9, 10 ]), "expecting [ 0, 1, 3, 4, 7, 9, 10 ]");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DataRow(new[] {1, 5, 9, 10, 11, 12}, new[] {1, 5, 9}, 9)]
|
||||
|
@ -37,5 +54,21 @@ namespace BizHawk.Tests.Common.CustomCollections
|
|||
sortlist.RemoveAfter(removeItem);
|
||||
Assert.IsTrue(sortlist.ToArray().SequenceEqual(after));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestSortedListSetIndexer()
|
||||
{
|
||||
SortedList<int> list = new([ 1, 3, 4 ]);
|
||||
Assert.ThrowsException<NotSupportedException>(() => list[1] = 9, "setting [1] out-of-order should throw");
|
||||
list[1] = 2;
|
||||
Assert.IsTrue(list.SequenceEqual([ 1, 2, 4 ]), "expecting [ 1, 2, 4 ]");
|
||||
Assert.ThrowsException<NotSupportedException>(() => list[0] = 9, "setting [0] out-of-order should throw");
|
||||
list[0] = 0;
|
||||
Assert.ThrowsException<NotSupportedException>(() => list[2] = 0, "setting [^1] out-of-order should throw");
|
||||
list[2] = 9;
|
||||
Assert.ThrowsException</*NotSupportedException*/ArgumentOutOfRangeException>(() => list[3] = 0, "setting [^0] (appending) out-of-order should throw");
|
||||
Assert.ThrowsException<ArgumentOutOfRangeException>(() => list[3] = 10, "setting [^0] (appending) properly should throw"); // to match BCL `List<T>`
|
||||
Assert.IsTrue(list.SequenceEqual([ 0, 2, 9 ]), "expecting [ 0, 2, 9 ]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue