diff --git a/src/ObservableCollections/ObservableHashSet.cs b/src/ObservableCollections/ObservableHashSet.cs new file mode 100644 index 0000000..821ea3d --- /dev/null +++ b/src/ObservableCollections/ObservableHashSet.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace ObservableCollections +{ + public sealed partial class ObservableHashSet + { + //// TODO:not yet + //readonly LinkedList list; + + //public ObservableHashSet(LinkedList list) + //{ + // this.list = list; + //} + } +} diff --git a/src/ObservableCollections/ObservableLinkedList.Views.cs b/src/ObservableCollections/ObservableLinkedList.Views.cs new file mode 100644 index 0000000..51a3b03 --- /dev/null +++ b/src/ObservableCollections/ObservableLinkedList.Views.cs @@ -0,0 +1,111 @@ +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace ObservableCollections +{ + public sealed partial class ObservableLinkedList : IReadOnlyCollection, IObservableCollection> + { + public ISynchronizedView, TView> CreateView(Func, TView> transform, bool reverse = false) + { + throw new NotImplementedException(); + } + + public ISynchronizedView, TView> CreateSortedView(Func, TKey> identitySelector, Func, TView> transform, IComparer> comparer) where TKey : notnull + { + throw new NotImplementedException(); + } + + public ISynchronizedView, TView> CreateSortedView(Func, TKey> identitySelector, Func, TView> transform, IComparer viewComparer) where TKey : notnull + { + throw new NotImplementedException(); + } + + sealed class View : ISynchronizedView, TView> + { + readonly ObservableLinkedList source; + readonly LinkedList<(LinkedListNode, TView)> list; + readonly Func, TView> selector; + + public View(ObservableLinkedList source) + { + this.source = source; + + lock (source.SyncRoot) + { + // TODO:get map + source.CollectionChanged += SourceCollectionChanged; + } + } + + + public object SyncRoot => throw new NotImplementedException(); + public event NotifyCollectionChangedEventHandler>? RoutingCollectionChanged; + public event Action? CollectionStateChanged; + + + public int Count => throw new NotImplementedException(); + + + public void AttachFilter(ISynchronizedViewFilter, TView> filter) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public IEnumerator<(LinkedListNode Value, TView View)> GetEnumerator() + { + throw new NotImplementedException(); + } + + public void ResetFilter(Action, TView>? resetAction) + { + throw new NotImplementedException(); + } + + public INotifyCollectionChangedSynchronizedView, TView> WithINotifyCollectionChanged() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + + private void SourceCollectionChanged(in NotifyCollectionChangedEventArgs> e) + { + lock (SyncRoot) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + { + // AddAfter + if (e.OldItem != null) + { + } + + } + break; + case NotifyCollectionChangedAction.Remove: + break; + case NotifyCollectionChangedAction.Replace: + break; + case NotifyCollectionChangedAction.Move: + break; + case NotifyCollectionChangedAction.Reset: + break; + default: + break; + } + } + } + } + } +} diff --git a/src/ObservableCollections/ObservableLinkedList.cs b/src/ObservableCollections/ObservableLinkedList.cs index afd03ca..60e1eff 100644 --- a/src/ObservableCollections/ObservableLinkedList.cs +++ b/src/ObservableCollections/ObservableLinkedList.cs @@ -1,15 +1,143 @@ -using System.Collections.Generic; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; namespace ObservableCollections { - public sealed partial class ObservableLinkedList + // TODO:Remove this??? + public sealed partial class ObservableLinkedList : IReadOnlyCollection, IObservableCollection> { - // TODO:not yet readonly LinkedList list; + public readonly object SyncRoot = new object(); - public ObservableLinkedList(LinkedList list) + public event NotifyCollectionChangedEventHandler>? CollectionChanged; + + public ObservableLinkedList() { - this.list = list; + this.list = new LinkedList(); + } + + public ObservableLinkedList(IEnumerable collection) + { + this.list = new LinkedList(collection); + } + + // TODO: First, Last + // Find, FindLast + + public int Count + { + get + { + lock (SyncRoot) + { + return list.Count; + } + } + } + + public LinkedListNode AddFirst(T item) + { + lock (SyncRoot) + { + var node = list.AddFirst(item); + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs>.Add(node, 0)); + return node; + } + } + + public LinkedListNode AddLast(T item) + { + lock (SyncRoot) + { + var index = list.Count; + var node = list.AddLast(item); + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs>.Add(node, index)); + return node; + } + } + + public LinkedListNode AddBefore(LinkedListNode node, T value) + { + lock (SyncRoot) + { + var newNode = list.AddBefore(node, value); + + // list. + + // special event, oldItem is target, newStartingIndex:-1 = before + var ev = new NotifyCollectionChangedEventArgs>( + NotifyCollectionChangedAction.Add, isSingleItem: true, + newItem: newNode, oldItem: node, newStartingIndex: -1); + + CollectionChanged?.Invoke(ev); + return newNode; + } + } + + public LinkedListNode AddAfter(LinkedListNode node, T value) + { + lock (SyncRoot) + { + var newNode = list.AddAfter(node, value); + + // special event, oldItem is target, newStartingIndex:1 = after + var ev = new NotifyCollectionChangedEventArgs>( + NotifyCollectionChangedAction.Add, isSingleItem: true, + newItem: newNode, oldItem: node, newStartingIndex: 1); + + CollectionChanged?.Invoke(ev); + return newNode; + } + } + + public void RemoveLast() + { + lock (SyncRoot) + { + var last = list.Last; + list.RemoveLast(); + if (last != null) + { + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs>.Remove(last, -1)); + } + } + } + + public void RemoveFirst() + { + lock (SyncRoot) + { + var first = list.First; + list.RemoveFirst(); + if (first != null) + { + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs>.Remove(first, -1)); + } + } + } + + public void Remove(LinkedListNode item) + { + lock (SyncRoot) + { + list.Remove(item); + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs>.Remove(item, -1)); + } + } + + + + // TODO: GetEnumerator + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); } } } diff --git a/src/ObservableCollections/ObservableQueue.cs b/src/ObservableCollections/ObservableQueue.cs index 008fb1b..c4a9de0 100644 --- a/src/ObservableCollections/ObservableQueue.cs +++ b/src/ObservableCollections/ObservableQueue.cs @@ -1,7 +1,9 @@ using ObservableCollections.Internal; using System; +using System.Buffers; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -93,18 +95,70 @@ namespace ObservableCollections } } - public void Dequeue() + public T Dequeue() { - // this.queue. - - - + lock (SyncRoot) + { + var index = queue.Count - 1; + var v = queue.Dequeue(); + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs.Remove(v, index)); + return v; + } } - // TryDequeue + public bool TryDequeue([MaybeNullWhen(false)] out T result) + { + lock (SyncRoot) + { + var index = queue.Count - 1; + if (queue.TryDequeue(out result)) + { + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs.Remove(result, index)); + return true; + } + return false; + } + } - // DequeueRange + public void DequeueRange(int count) + { + lock (SyncRoot) + { + var startIndex = queue.Count - count; + var dest = ArrayPool.Shared.Rent(count); + try + { + for (int i = 0; i < count; i++) + { + dest[0] = queue.Dequeue(); + } + + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs.Remove(dest.AsSpan(0, count), startIndex)); + } + finally + { + ArrayPool.Shared.Return(dest); + } + } + } + + public void DequeueRange(Span dest) + { + lock (SyncRoot) + { + var count = queue.Count; + var destCount = dest.Length; + for (int i = 0; i < dest.Length; i++) + { + dest[0] = queue.Dequeue(); + } + + CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs.Remove(dest, count - queue.Count)); + } + } + + // TODO: void Clear() { }