remove unused new observable collection
This commit is contained in:
@@ -1,227 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace ObservableCollections
|
||||
{
|
||||
public partial class ObservableSortedSet<T> : IReadOnlyCollection<T>, IObservableCollection<T>
|
||||
{
|
||||
public ISynchronizedView<T, TView> CreateView<TView>(Func<T, TView> transform)
|
||||
{
|
||||
return new View<TView>(this, transform);
|
||||
}
|
||||
|
||||
sealed class View<TView> : ISynchronizedView<T, TView>
|
||||
{
|
||||
public ISynchronizedViewFilter<T, TView> Filter
|
||||
{
|
||||
get { lock (SyncRoot) return filter; }
|
||||
}
|
||||
|
||||
readonly ObservableSortedSet<T> source;
|
||||
readonly Func<T, TView> selector;
|
||||
readonly Dictionary<T, (T, TView)> dict;
|
||||
int filteredCount;
|
||||
|
||||
ISynchronizedViewFilter<T, TView> filter;
|
||||
|
||||
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
||||
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||
public event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
|
||||
|
||||
public object SyncRoot { get; }
|
||||
|
||||
public View(ObservableSortedSet<T> source, Func<T, TView> selector)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||
this.SyncRoot = new object();
|
||||
lock (source.SyncRoot)
|
||||
{
|
||||
this.dict = source._set.ToDictionary(x => x, x => (x, selector(x)));
|
||||
this.filteredCount = dict.Count;
|
||||
this.source.CollectionChanged += SourceCollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return filteredCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int UnfilteredCount
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return dict.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AttachFilter(ISynchronizedViewFilter<T, TView> filter)
|
||||
{
|
||||
if (filter.IsNullFilter())
|
||||
{
|
||||
ResetFilter();
|
||||
return;
|
||||
}
|
||||
|
||||
lock (SyncRoot)
|
||||
{
|
||||
this.filter = filter;
|
||||
this.filteredCount = 0;
|
||||
foreach (var (_, (value, view)) in dict)
|
||||
{
|
||||
if (filter.IsMatch(value, view))
|
||||
{
|
||||
filteredCount++;
|
||||
}
|
||||
}
|
||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetFilter()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||
this.filteredCount = dict.Count;
|
||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||
}
|
||||
}
|
||||
|
||||
public ISynchronizedViewList<TView> ToViewList()
|
||||
{
|
||||
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: true);
|
||||
}
|
||||
|
||||
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged()
|
||||
{
|
||||
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false);
|
||||
}
|
||||
|
||||
public NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged(ICollectionEventDispatcher? collectionEventDispatcher)
|
||||
{
|
||||
return new FiltableSynchronizedViewList<T, TView>(this, isSupportRangeFeature: false, collectionEventDispatcher);
|
||||
}
|
||||
|
||||
public IEnumerator<TView> GetEnumerator()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
foreach (var item in dict)
|
||||
{
|
||||
if (filter.IsMatch(item.Value))
|
||||
{
|
||||
yield return item.Value.Item2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public IEnumerable<(T Value, TView View)> Filtered
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
foreach (var item in dict)
|
||||
{
|
||||
if (filter.IsMatch(item.Value))
|
||||
{
|
||||
yield return item.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<(T Value, TView View)> Unfiltered
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
foreach (var item in dict)
|
||||
{
|
||||
yield return item.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.source.CollectionChanged -= SourceCollectionChanged;
|
||||
}
|
||||
|
||||
private void SourceCollectionChanged(in NotifyCollectionChangedEventArgs<T> e)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
switch (e.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
if (e.IsSingleItem)
|
||||
{
|
||||
var v = (e.NewItem, selector(e.NewItem));
|
||||
dict.Add(e.NewItem, v);
|
||||
this.InvokeOnAdd(ref filteredCount, ViewChanged, RejectedViewChanged, v, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
var i = e.NewStartingIndex;
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var v = (item, selector(item));
|
||||
dict.Add(item, v);
|
||||
this.InvokeOnAdd(ref filteredCount, ViewChanged, RejectedViewChanged, v, i++);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
if (e.IsSingleItem)
|
||||
{
|
||||
if (dict.Remove(e.OldItem, out var value))
|
||||
{
|
||||
this.InvokeOnRemove(ref filteredCount, ViewChanged, RejectedViewChanged, value, -1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in e.OldItems)
|
||||
{
|
||||
if (dict.Remove(item, out var value))
|
||||
{
|
||||
this.InvokeOnRemove(ref filteredCount, ViewChanged, RejectedViewChanged, value, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
dict.Clear();
|
||||
this.InvokeOnReset(ref filteredCount, ViewChanged);
|
||||
break;
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CollectionStateChanged?.Invoke(e.Action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,318 +0,0 @@
|
||||
using ObservableCollections.Internal;
|
||||
using System.Collections;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
// Courtesy of Copilot Agent
|
||||
// Replace with https://github.com/Cysharp/ObservableCollections/pull/111 if it gets merged
|
||||
namespace ObservableCollections
|
||||
{
|
||||
// can not implements ISet<T> because set operation can not get added/removed values.
|
||||
public partial class ObservableSortedSet<T> : IReadOnlySet<T>, IReadOnlyCollection<T>, IObservableCollection<T> where T : notnull
|
||||
{
|
||||
private readonly SortedSet<T> _set;
|
||||
public object SyncRoot { get; } = new object();
|
||||
|
||||
public ObservableSortedSet()
|
||||
{
|
||||
_set = new SortedSet<T>();
|
||||
}
|
||||
|
||||
public ObservableSortedSet(IComparer<T>? comparer)
|
||||
{
|
||||
_set = new SortedSet<T>(comparer: comparer);
|
||||
}
|
||||
|
||||
public ObservableSortedSet(IEnumerable<T> collection)
|
||||
{
|
||||
_set = new SortedSet<T>(collection: collection);
|
||||
}
|
||||
|
||||
public ObservableSortedSet(IEnumerable<T> collection, IComparer<T>? comparer)
|
||||
{
|
||||
_set = new SortedSet<T>(collection: collection, comparer: comparer);
|
||||
}
|
||||
|
||||
public event NotifyCollectionChangedEventHandler<T>? CollectionChanged;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public bool Add(T item)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (_set.Add(item))
|
||||
{
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(item, -1));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<T> items)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (!items.TryGetNonEnumeratedCount(out var capacity))
|
||||
{
|
||||
capacity = 4;
|
||||
}
|
||||
|
||||
using (var list = new ResizableArray<T>(capacity))
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (_set.Add(item))
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(list.Span, -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(T[] items)
|
||||
{
|
||||
AddRange(items.AsSpan());
|
||||
}
|
||||
|
||||
public void AddRange(ReadOnlySpan<T> items)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
using (var list = new ResizableArray<T>(items.Length))
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (_set.Add(item))
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(list.Span, -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (_set.Remove(item))
|
||||
{
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Remove(item, -1));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRange(IEnumerable<T> items)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (!items.TryGetNonEnumeratedCount(out var capacity))
|
||||
{
|
||||
capacity = 4;
|
||||
}
|
||||
|
||||
using (var list = new ResizableArray<T>(capacity))
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (_set.Remove(item))
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Remove(list.Span, -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRange(T[] items)
|
||||
{
|
||||
RemoveRange(items.AsSpan());
|
||||
}
|
||||
|
||||
public void RemoveRange(ReadOnlySpan<T> items)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
using (var list = new ResizableArray<T>(items.Length))
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (_set.Remove(item))
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Remove(list.Span, -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
_set.Clear();
|
||||
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Reset());
|
||||
}
|
||||
}
|
||||
|
||||
#if !NETSTANDARD2_0 && !NET_STANDARD_2_0 && !NET_4_6
|
||||
|
||||
public bool TryGetValue(T equalValue, [MaybeNullWhen(false)] out T actualValue)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.TryGetValue(equalValue, out actualValue);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsProperSubsetOf(IEnumerable<T> other)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.IsProperSubsetOf(other);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsProperSupersetOf(IEnumerable<T> other)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.IsProperSupersetOf(other);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSubsetOf(IEnumerable<T> other)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.IsSubsetOf(other);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSupersetOf(IEnumerable<T> other)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.IsSupersetOf(other);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Overlaps(IEnumerable<T> other)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.Overlaps(other);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SetEquals(IEnumerable<T> other)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.SetEquals(other);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
foreach (var item in _set)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IComparer<T> Comparer
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.Comparer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SortedSet-specific properties
|
||||
public T? Min
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.Count > 0 ? _set.Min : default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T? Max
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.Count > 0 ? _set.Max : default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SortedSet-specific methods
|
||||
public IEnumerable<T> Reverse()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.Reverse().ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetViewBetween(T lowerValue, T upperValue)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
return _set.GetViewBetween(lowerValue, upperValue).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user