new filter

This commit is contained in:
neuecc 2021-08-09 19:06:01 +09:00
parent c0fb7375e0
commit 59300d8ee8
10 changed files with 444 additions and 66 deletions

View File

@ -7,32 +7,42 @@ namespace ObservableCollections
bool IsMatch(T value, TView view);
void WhenTrue(T value, TView view);
void WhenFalse(T value, TView view);
void OnCollectionChanged(ChangedKind changedKind, T value, TView view);
}
public enum ChangedKind
{
Add, Remove
}
public class SynchronizedViewFilter<T, TView> : ISynchronizedViewFilter<T, TView>
{
public static readonly ISynchronizedViewFilter<T, TView> AlwaysTrue = new TrueViewFilter();
public static readonly ISynchronizedViewFilter<T, TView> Null = new NullViewFilter();
readonly Func<T, TView, bool> isMatch;
readonly Action<T, TView>? whenTrue;
readonly Action<T, TView>? whenFalse;
readonly Action<ChangedKind, T, TView>? onCollectionChanged;
public SynchronizedViewFilter(Func<T, TView, bool> isMatch, Action<T, TView>? whenTrue, Action<T, TView>? whenFalse)
public SynchronizedViewFilter(Func<T, TView, bool> isMatch, Action<T, TView>? whenTrue, Action<T, TView>? whenFalse, Action<ChangedKind, T, TView>? onCollectionChanged)
{
this.isMatch = isMatch;
this.whenTrue = whenTrue;
this.whenFalse = whenFalse;
this.onCollectionChanged = onCollectionChanged;
}
public bool IsMatch(T value, TView view) => isMatch(value, view);
public void WhenFalse(T value, TView view) => whenFalse?.Invoke(value, view);
public void WhenTrue(T value, TView view) => whenTrue?.Invoke(value, view);
public void OnCollectionChanged(ChangedKind changedKind, T value, TView view) => onCollectionChanged?.Invoke(changedKind, value, view);
class TrueViewFilter : ISynchronizedViewFilter<T, TView>
class NullViewFilter : ISynchronizedViewFilter<T, TView>
{
public bool IsMatch(T value, TView view) => true;
public void WhenFalse(T value, TView view) { }
public void WhenTrue(T value, TView view) { }
public void OnCollectionChanged(ChangedKind changedKind, T value, TView view) { }
}
}
@ -40,20 +50,53 @@ namespace ObservableCollections
{
public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, TView, bool> filter)
{
source.AttachFilter(new SynchronizedViewFilter<T, TView>(filter, null, null));
source.AttachFilter(new SynchronizedViewFilter<T, TView>(filter, null, null, null));
}
public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, TView, bool> isMatch, Action<T, TView>? whenTrue, Action<T, TView>? whenFalse)
{
source.AttachFilter(new SynchronizedViewFilter<T, TView>(isMatch, whenTrue, whenFalse));
source.AttachFilter(new SynchronizedViewFilter<T, TView>(isMatch, whenTrue, whenFalse, null));
}
public static void Invoke<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T, TView) value)
public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, TView, bool> isMatch, Action<T, TView>? whenTrue, Action<T, TView>? whenFalse, Action<ChangedKind, T, TView>? onCollectionChanged)
{
Invoke(filter, value.Item1, value.Item2);
source.AttachFilter(new SynchronizedViewFilter<T, TView>(isMatch, whenTrue, whenFalse, onCollectionChanged));
}
public static void Invoke<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view)
public static bool IsNullFilter<T, TView>(this ISynchronizedViewFilter<T, TView> filter)
{
return filter == SynchronizedViewFilter<T, TView>.Null;
}
internal static void InvokeOnAdd<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value)
{
InvokeOnAdd(filter, value.value, value.view);
}
internal static void InvokeOnAdd<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view)
{
if (filter.IsMatch(value, view))
{
filter.WhenTrue(value, view);
}
else
{
filter.WhenFalse(value, view);
}
filter.OnCollectionChanged(ChangedKind.Add, value, view);
}
internal static void InvokeOnRemove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value)
{
InvokeOnRemove(filter, value.value, value.view);
}
internal static void InvokeOnRemove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view)
{
filter.OnCollectionChanged(ChangedKind.Remove, value, view);
}
internal static void InvokeOnAttach<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view)
{
if (filter.IsMatch(value, view))
{

View File

@ -23,7 +23,7 @@ namespace ObservableCollections.Internal
public FreezedView(IEnumerable<T> source, Func<T, TView> selector, bool reverse)
{
this.reverse = reverse;
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
this.list = source.Select(x => (x, selector(x))).ToList();
}
@ -54,7 +54,7 @@ namespace ObservableCollections.Internal
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
if (resetAction != null)
{
foreach (var (item, view) in list)
@ -103,7 +103,7 @@ namespace ObservableCollections.Internal
public FreezedSortableView(IEnumerable<T> source, Func<T, TView> selector)
{
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
this.array = source.Select(x => (x, selector(x))).ToArray();
}
@ -134,7 +134,7 @@ namespace ObservableCollections.Internal
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
if (resetAction != null)
{
foreach (var (item, view) in array)

View File

@ -47,7 +47,7 @@ namespace ObservableCollections
{
this.source = source;
this.selector = selector;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
this.SyncRoot = new object();
lock (source.SyncRoot)
{
@ -83,7 +83,7 @@ namespace ObservableCollections
this.filter = filter;
foreach (var v in dict)
{
filter.Invoke(new KeyValuePair<TKey, TValue>(v.Key, v.Value.Item1), v.Value.Item2);
filter.InvokeOnAttach(new KeyValuePair<TKey, TValue>(v.Key, v.Value.Item1), v.Value.Item2);
}
}
}
@ -92,7 +92,7 @@ namespace ObservableCollections
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
if (resetAction != null)
{
foreach (var v in dict)
@ -134,25 +134,40 @@ namespace ObservableCollections
{
var v = selector(e.NewItem);
dict.Add(e.NewItem.Key, (e.NewItem.Value, v));
filter.Invoke(new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value), v);
filter.InvokeOnAdd(new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value), v);
}
break;
case NotifyCollectionChangedAction.Remove:
{
dict.Remove(e.OldItem.Key);
if (dict.Remove(e.OldItem.Key, out var v))
{
filter.InvokeOnRemove((new KeyValuePair<TKey, TValue>(e.OldItem.Key, v.Item1), v.Item2));
}
}
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
{
dict.Remove(e.OldItem.Key);
if (dict.Remove(e.OldItem.Key, out var oldView))
{
filter.InvokeOnRemove((new KeyValuePair<TKey, TValue>(e.OldItem.Key, oldView.Item1), oldView.Item2));
}
var v = selector(e.NewItem);
dict[e.NewItem.Key] = (e.NewItem.Value, v);
filter.Invoke(new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value), v);
filter.InvokeOnAdd(new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value), v);
}
break;
case NotifyCollectionChangedAction.Reset:
{
if (!filter.IsNullFilter())
{
foreach (var item in dict)
{
filter.InvokeOnRemove((new KeyValuePair<TKey, TValue>(item.Key, item.Value.Item1), item.Value.Item2));
}
}
dict.Clear();
}
break;
@ -177,7 +192,7 @@ namespace ObservableCollections
{
this.source = source;
this.selector = selector;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
this.SyncRoot = new object();
lock (source.SyncRoot)
{
@ -217,7 +232,7 @@ namespace ObservableCollections
this.filter = filter;
foreach (var v in dict)
{
filter.Invoke(new KeyValuePair<TKey, TValue>(v.Key.Key, v.Key.Value), v.Value);
filter.InvokeOnAttach(new KeyValuePair<TKey, TValue>(v.Key.Key, v.Key.Value), v.Value);
}
}
}
@ -226,7 +241,7 @@ namespace ObservableCollections
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
if (resetAction != null)
{
foreach (var v in dict)
@ -269,27 +284,41 @@ namespace ObservableCollections
var v = selector(e.NewItem);
var k = new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value);
dict.Add(k, v);
filter.Invoke(k, v);
filter.InvokeOnAdd(k, v);
}
break;
case NotifyCollectionChangedAction.Remove:
{
dict.Remove(e.OldItem);
if (dict.Remove(e.OldItem, out var value))
{
filter.InvokeOnRemove(e.OldItem, value);
}
}
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
{
var k = new KeyValuePair<TKey, TValue>(e.OldItem.Key, e.OldItem.Value);
dict.Remove(k);
if (dict.Remove(k, out var oldValue))
{
filter.InvokeOnRemove(k, oldValue);
}
var v = selector(e.NewItem);
var nk = new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value);
dict[nk] = v;
filter.Invoke(nk, v);
filter.InvokeOnAdd(nk, v);
}
break;
case NotifyCollectionChangedAction.Reset:
{
if (!filter.IsNullFilter())
{
foreach (var item in dict)
{
filter.InvokeOnRemove(item.Key, item.Value);
}
}
dict.Clear();
}
break;
@ -317,7 +346,7 @@ namespace ObservableCollections
{
this.source = source;
this.selector = selector;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
this.SyncRoot = new object();
lock (source.SyncRoot)
{
@ -360,7 +389,7 @@ namespace ObservableCollections
this.filter = filter;
foreach (var v in dict)
{
filter.Invoke(v.Value, v.Key);
filter.InvokeOnAttach(v.Value, v.Key);
}
}
}
@ -369,7 +398,7 @@ namespace ObservableCollections
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
if (resetAction != null)
{
foreach (var v in dict)
@ -413,7 +442,7 @@ namespace ObservableCollections
var k = new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value);
dict.Add(v, k);
viewMap.Add(e.NewItem.Key, v);
filter.Invoke(k, v);
filter.InvokeOnAdd(k, v);
}
break;
case NotifyCollectionChangedAction.Remove:
@ -421,6 +450,7 @@ namespace ObservableCollections
if (viewMap.Remove(e.OldItem.Key, out var view))
{
dict.Remove(view);
filter.InvokeOnRemove(e.OldItem, view);
}
}
break;
@ -429,19 +459,30 @@ namespace ObservableCollections
{
if (viewMap.Remove(e.OldItem.Key, out var view))
{
dict.Remove(view);
if (dict.Remove(view, out var oldView))
{
filter.InvokeOnRemove(e.OldItem, view);
}
var v = selector(e.NewItem);
var k = new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value);
dict[v] = k;
viewMap[e.NewItem.Key] = v;
filter.Invoke(k, v);
filter.InvokeOnAdd(k, v);
}
break;
}
case NotifyCollectionChangedAction.Reset:
{
if (!filter.IsNullFilter())
{
foreach (var item in dict)
{
filter.InvokeOnRemove(item.Value, item.Key);
}
}
dict.Clear();
viewMap.Clear();
}
break;
default:

View File

@ -18,9 +18,9 @@ namespace ObservableCollections
this.dictionary = new Dictionary<TKey, TValue>();
}
public ObservableDictionary(Dictionary<TKey, TValue> dictionary)
public ObservableDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection)
{
this.dictionary = dictionary;
this.dictionary = new Dictionary<TKey, TValue>(collection);
}
public event NotifyCollectionChangedEventHandler<KeyValuePair<TKey, TValue>>? CollectionChanged;

View File

@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace ObservableCollections
{
public sealed partial class ObservableLinkedList<T>
{
// TODO:not yet
readonly LinkedList<T> list;
public ObservableLinkedList(LinkedList<T> list)
{
this.list = list;
}
}
}

View File

@ -45,7 +45,7 @@ namespace ObservableCollections
this.source = source;
this.selector = selector;
this.reverse = reverse;
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
this.SyncRoot = new object();
lock (source.SyncRoot)
{
@ -54,10 +54,6 @@ namespace ObservableCollections
}
}
protected virtual void DoSort()
{
}
public int Count
{
get
@ -76,7 +72,7 @@ namespace ObservableCollections
this.filter = filter;
foreach (var (value, view) in list)
{
filter.Invoke(value, view);
filter.InvokeOnAttach(value, view);
}
}
}
@ -85,7 +81,7 @@ namespace ObservableCollections
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
if (resetAction != null)
{
foreach (var (item, view) in list)
@ -139,7 +135,7 @@ namespace ObservableCollections
{
var v = (e.NewItem, selector(e.NewItem));
list.Add(v);
filter.Invoke(v);
filter.InvokeOnAdd(v);
}
else
{
@ -147,7 +143,7 @@ namespace ObservableCollections
{
var v = (item, selector(item));
list.Add(v);
filter.Invoke(v);
filter.InvokeOnAdd(v);
}
}
}
@ -158,7 +154,7 @@ namespace ObservableCollections
{
var v = (e.NewItem, selector(e.NewItem));
list.Insert(e.NewStartingIndex, v);
filter.Invoke(v);
filter.InvokeOnAdd(v);
}
else
{
@ -169,7 +165,7 @@ namespace ObservableCollections
{
var v = (span[i], selector(span[i]));
newArray[i] = v;
filter.Invoke(v);
filter.InvokeOnAdd(v);
}
list.InsertRange(e.NewStartingIndex, newArray);
}
@ -178,10 +174,22 @@ namespace ObservableCollections
case NotifyCollectionChangedAction.Remove:
if (e.IsSingleItem)
{
var v = list[e.OldStartingIndex];
list.RemoveAt(e.OldStartingIndex);
filter.InvokeOnRemove(v.Item1, v.Item2);
}
else
{
if (!filter.IsNullFilter())
{
var len = e.OldStartingIndex + e.OldItems.Length;
for (int i = e.OldStartingIndex; i < len; i++)
{
var v = list[i];
filter.InvokeOnRemove(v.Item1, v.Item2);
}
}
list.RemoveRange(e.OldStartingIndex, e.OldItems.Length);
}
break;
@ -189,25 +197,39 @@ namespace ObservableCollections
// ObservableList does not support replace range
{
var v = (e.NewItem, selector(e.NewItem));
var oldItem = list[e.NewStartingIndex];
list[e.NewStartingIndex] = v;
filter.InvokeOnRemove(oldItem);
filter.InvokeOnAdd(v);
break;
}
case NotifyCollectionChangedAction.Move:
{
var v = (e.NewItem, selector(e.NewItem));
var removeItem = list[e.OldStartingIndex];
list.RemoveAt(e.OldStartingIndex);
list.Insert(e.NewStartingIndex, v);
filter.Invoke(v);
filter.InvokeOnRemove(removeItem);
filter.InvokeOnAdd(v);
}
break;
case NotifyCollectionChangedAction.Reset:
if (!filter.IsNullFilter())
{
foreach (var item in list)
{
filter.InvokeOnRemove(item);
}
}
list.Clear();
break;
default:
break;
}
DoSort();
RoutingCollectionChanged?.Invoke(e);
CollectionStateChanged?.Invoke(e.Action);
}
@ -234,7 +256,7 @@ namespace ObservableCollections
this.source = source;
this.identitySelector = identitySelector;
this.transform = transform;
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
lock (source.SyncRoot)
{
var dict = new SortedDictionary<(T, TKey), (T, TView)>(new Comparer(comparer));
@ -268,7 +290,7 @@ namespace ObservableCollections
this.filter = filter;
foreach (var (_, (value, view)) in list)
{
filter.Invoke(value, view);
filter.InvokeOnAttach(value, view);
}
}
}
@ -277,7 +299,7 @@ namespace ObservableCollections
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
if (resetAction != null)
{
foreach (var (_, (value, view)) in list)
@ -323,7 +345,7 @@ namespace ObservableCollections
var view = transform(value);
var id = identitySelector(value);
list.Add((value, id), (value, view));
filter.Invoke(value, view);
filter.InvokeOnAdd(value, view);
}
else
{
@ -332,7 +354,7 @@ namespace ObservableCollections
var view = transform(value);
var id = identitySelector(value);
list.Add((value, id), (value, view));
filter.Invoke(value, view);
filter.InvokeOnAdd(value, view);
}
}
}
@ -343,14 +365,16 @@ namespace ObservableCollections
{
var value = e.OldItem;
var id = identitySelector(value);
list.Remove((value, id));
list.Remove((value, id), out var v);
filter.InvokeOnRemove(v.Value, v.View);
}
else
{
foreach (var value in e.OldItems)
{
var id = identitySelector(value);
list.Remove((value, id));
list.Remove((value, id), out var v);
filter.InvokeOnRemove(v.Value, v.View);
}
}
}
@ -361,16 +385,25 @@ namespace ObservableCollections
// Replace is remove old item and insert new item(same index on replace, difference index on move).
{
var oldValue = e.OldItem;
list.Remove((oldValue, identitySelector(oldValue)));
list.Remove((oldValue, identitySelector(oldValue)), out var oldView);
var value = e.NewItem;
var view = transform(value);
var id = identitySelector(value);
list.Add((value, id), (value, view));
filter.Invoke(value, view);
filter.InvokeOnRemove(oldView);
filter.InvokeOnAdd(value, view);
}
break;
case NotifyCollectionChangedAction.Reset:
if (!filter.IsNullFilter())
{
foreach (var item in list)
{
filter.InvokeOnRemove(item.Value);
}
}
list.Clear();
break;
default:
@ -425,7 +458,7 @@ namespace ObservableCollections
this.source = source;
this.identitySelector = identitySelector;
this.transform = transform;
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
lock (source.SyncRoot)
{
var dict = new SortedDictionary<(TView, TKey), (T, TView)>(new Comparer(comparer));
@ -462,7 +495,7 @@ namespace ObservableCollections
this.filter = filter;
foreach (var (_, (value, view)) in list)
{
filter.Invoke(value, view);
filter.InvokeOnAttach(value, view);
}
}
}
@ -471,7 +504,7 @@ namespace ObservableCollections
{
lock (SyncRoot)
{
this.filter = SynchronizedViewFilter<T, TView>.AlwaysTrue;
this.filter = SynchronizedViewFilter<T, TView>.Null;
if (resetAction != null)
{
foreach (var (_, (value, view)) in list)
@ -518,7 +551,7 @@ namespace ObservableCollections
var id = identitySelector(value);
list.Add((view, id), (value, view));
viewMap.Add(id, view);
filter.Invoke(value, view);
filter.InvokeOnAdd(value, view);
}
else
{
@ -528,7 +561,7 @@ namespace ObservableCollections
var id = identitySelector(value);
list.Add((view, id), (value, view));
viewMap.Add(id, view);
filter.Invoke(value, view);
filter.InvokeOnAdd(value, view);
}
}
}
@ -541,7 +574,8 @@ namespace ObservableCollections
var id = identitySelector(value);
if (viewMap.Remove(id, out var view))
{
list.Remove((view, id));
list.Remove((view, id), out var v);
filter.InvokeOnRemove(v);
}
}
else
@ -551,7 +585,8 @@ namespace ObservableCollections
var id = identitySelector(value);
if (viewMap.Remove(id, out var view))
{
list.Remove((view, id));
list.Remove((view, id), out var v);
filter.InvokeOnRemove(v);
}
}
}
@ -567,6 +602,7 @@ namespace ObservableCollections
if (viewMap.Remove(oldKey, out var oldView))
{
list.Remove((oldView, oldKey));
filter.InvokeOnRemove(oldValue, oldView);
}
var value = e.NewItem;
@ -574,11 +610,20 @@ namespace ObservableCollections
var id = identitySelector(value);
list.Add((view, id), (value, view));
viewMap.Add(id, view);
filter.Invoke(value, view);
filter.InvokeOnAdd(value, view);
}
break;
case NotifyCollectionChangedAction.Reset:
if (!filter.IsNullFilter())
{
foreach (var item in list)
{
filter.InvokeOnRemove(item.Value);
}
}
list.Clear();
viewMap.Clear();
break;
default:
break;

View File

@ -17,9 +17,14 @@ namespace ObservableCollections
list = new List<T>();
}
public ObservableList(IEnumerable<T> source)
public ObservableList(int capacity)
{
list = source.ToList();
list = new List<T>(capacity);
}
public ObservableList(IEnumerable<T> collection)
{
list = collection.ToList();
}
public T this[int index]

View File

@ -0,0 +1,156 @@
using ObservableCollections.Internal;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ObservableCollections
{
public sealed partial class ObservableQueue<T> : IReadOnlyCollection<T>, IObservableCollection<T>
{
readonly Queue<T> queue;
public readonly object SyncRoot = new object();
public ObservableQueue()
{
this.queue = new Queue<T>();
}
public ObservableQueue(int capacity)
{
this.queue = new Queue<T>(capacity);
}
public ObservableQueue(IEnumerable<T> collection)
{
this.queue = new Queue<T>(collection);
}
public event NotifyCollectionChangedEventHandler<T>? CollectionChanged;
public int Count
{
get
{
lock (SyncRoot)
{
return queue.Count;
}
}
}
public void Enqueue(T item)
{
lock (SyncRoot)
{
var index = queue.Count;
queue.Enqueue(item);
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(item, index));
}
}
public void EnqueueRange(IEnumerable<T> items)
{
lock (SyncRoot)
{
var index = queue.Count;
using (var xs = new CopyedCollection<T>(items))
{
foreach (var item in xs.Span)
{
queue.Enqueue(item);
}
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(xs.Span, index));
}
}
}
public void EnqueueRange(T[] items)
{
lock (SyncRoot)
{
var index = queue.Count;
foreach (var item in items)
{
queue.Enqueue(item);
}
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(items, index));
}
}
public void EnqueueRange(ReadOnlySpan<T> items)
{
lock (SyncRoot)
{
var index = queue.Count;
foreach (var item in items)
{
queue.Enqueue(item);
}
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(items, index));
}
}
public void Dequeue()
{
// this.queue.
}
// TryDequeue
// DequeueRange
void Clear()
{
}
//bool Contains(T item)
//{
//}
//void CopyTo(T[] array, int arrayIndex);
// Peek
// ToArray
// TrimExcess
// EnsureCapacity
// TryPeek
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
public ISynchronizedView<T, TView> CreateView<TView>(Func<T, TView> transform, bool reverse = false)
{
throw new NotImplementedException();
}
public ISynchronizedView<T, TView> CreateSortedView<TKey, TView>(Func<T, TKey> identitySelector, Func<T, TView> transform, IComparer<T> comparer) where TKey : notnull
{
throw new NotImplementedException();
}
public ISynchronizedView<T, TView> CreateSortedView<TKey, TView>(Func<T, TKey> identitySelector, Func<T, TView> transform, IComparer<TView> viewComparer) where TKey : notnull
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,48 @@
namespace ObservableCollections
{
public sealed partial class ObservableRingBuffer<T>
{
// TODO:not yet.
readonly T[] buffer;
public ObservableRingBuffer(int capacity)
{
this.buffer = new T[capacity];
}
public int Count => buffer.Length;
public T this[int index]
{
get
{
return this.buffer[index];
}
set
{
}
}
public void AddLast()
{
// AddLast
// AddFirst
//new LinkedList<int>().remo
//new Stack<int>().Push
}
public void AddFirst()
{
}
public void RemoveLast()
{
}
public void RemoveFirst()
{
}
// GetReverseEnumerable
}
}

View File

@ -0,0 +1,25 @@
using System.Collections.Generic;
namespace ObservableCollections
{
public sealed partial class ObservableStack<T>
{
// TODO:not yet.
readonly Stack<T> stack;
public ObservableStack(Stack<T> stack)
{
this.stack = stack;
}
public void Push(T item)
{
stack.Push(item);
}
public void Pop(T item)
{
stack.Pop();
}
}
}