lock yield return
This commit is contained in:
parent
5eff62bb5a
commit
70b0b4a5b4
@ -67,13 +67,28 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in list.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +162,16 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, array.AsEnumerable().GetEnumerator(), filter);
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in array)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
@ -88,7 +88,16 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, dict.Select(x => x.Value).GetEnumerator(), filter);
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Value.Value, item.Value.View))
|
||||||
|
{
|
||||||
|
yield return item.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
@ -13,7 +13,7 @@ namespace ObservableCollections.Internal
|
|||||||
readonly Func<T, TView> transform;
|
readonly Func<T, TView> transform;
|
||||||
readonly Func<T, TKey> identitySelector;
|
readonly Func<T, TKey> identitySelector;
|
||||||
readonly Dictionary<TKey, TView> viewMap; // view-map needs to use in remove.
|
readonly Dictionary<TKey, TView> viewMap; // view-map needs to use in remove.
|
||||||
readonly SortedDictionary<(TView View, TKey Key), (T Value, TView View)> list;
|
readonly SortedDictionary<(TView View, TKey Key), (T Value, TView View)> dict;
|
||||||
|
|
||||||
ISynchronizedViewFilter<T, TView> filter;
|
ISynchronizedViewFilter<T, TView> filter;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ namespace ObservableCollections.Internal
|
|||||||
dict.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
}
|
}
|
||||||
this.list = dict;
|
this.dict = dict;
|
||||||
this.source.CollectionChanged += SourceCollectionChanged;
|
this.source.CollectionChanged += SourceCollectionChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ namespace ObservableCollections.Internal
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return list.Count;
|
return dict.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ namespace ObservableCollections.Internal
|
|||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
foreach (var (_, (value, view)) in list)
|
foreach (var (_, (value, view)) in dict)
|
||||||
{
|
{
|
||||||
filter.InvokeOnAttach(value, view);
|
filter.InvokeOnAttach(value, view);
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ namespace ObservableCollections.Internal
|
|||||||
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
if (resetAction != null)
|
if (resetAction != null)
|
||||||
{
|
{
|
||||||
foreach (var (_, (value, view)) in list)
|
foreach (var (_, (value, view)) in dict)
|
||||||
{
|
{
|
||||||
resetAction(value, view);
|
resetAction(value, view);
|
||||||
}
|
}
|
||||||
@ -92,7 +92,17 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.Select(x => x.Value).GetEnumerator(), filter);
|
|
||||||
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Value.Value, item.Value.View))
|
||||||
|
{
|
||||||
|
yield return item.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
@ -116,7 +126,7 @@ namespace ObservableCollections.Internal
|
|||||||
var value = e.NewItem;
|
var value = e.NewItem;
|
||||||
var view = transform(value);
|
var view = transform(value);
|
||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
list.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
filter.InvokeOnAdd(value, view);
|
filter.InvokeOnAdd(value, view);
|
||||||
}
|
}
|
||||||
@ -126,7 +136,7 @@ namespace ObservableCollections.Internal
|
|||||||
{
|
{
|
||||||
var view = transform(value);
|
var view = transform(value);
|
||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
list.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
filter.InvokeOnAdd(value, view);
|
filter.InvokeOnAdd(value, view);
|
||||||
}
|
}
|
||||||
@ -141,7 +151,7 @@ namespace ObservableCollections.Internal
|
|||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
if (viewMap.Remove(id, out var view))
|
if (viewMap.Remove(id, out var view))
|
||||||
{
|
{
|
||||||
list.Remove((view, id), out var v);
|
dict.Remove((view, id), out var v);
|
||||||
filter.InvokeOnRemove(v);
|
filter.InvokeOnRemove(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,7 +162,7 @@ namespace ObservableCollections.Internal
|
|||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
if (viewMap.Remove(id, out var view))
|
if (viewMap.Remove(id, out var view))
|
||||||
{
|
{
|
||||||
list.Remove((view, id), out var v);
|
dict.Remove((view, id), out var v);
|
||||||
filter.InvokeOnRemove(v);
|
filter.InvokeOnRemove(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,14 +176,14 @@ namespace ObservableCollections.Internal
|
|||||||
var oldKey = identitySelector(oldValue);
|
var oldKey = identitySelector(oldValue);
|
||||||
if (viewMap.Remove(oldKey, out var oldView))
|
if (viewMap.Remove(oldKey, out var oldView))
|
||||||
{
|
{
|
||||||
list.Remove((oldView, oldKey));
|
dict.Remove((oldView, oldKey));
|
||||||
filter.InvokeOnRemove(oldValue, oldView);
|
filter.InvokeOnRemove(oldValue, oldView);
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = e.NewItem;
|
var value = e.NewItem;
|
||||||
var view = transform(value);
|
var view = transform(value);
|
||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
list.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
|
|
||||||
filter.InvokeOnAdd(value, view);
|
filter.InvokeOnAdd(value, view);
|
||||||
@ -193,12 +203,12 @@ namespace ObservableCollections.Internal
|
|||||||
case NotifyCollectionChangedAction.Reset:
|
case NotifyCollectionChangedAction.Reset:
|
||||||
if (!filter.IsNullFilter())
|
if (!filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
foreach (var item in list)
|
foreach (var item in dict)
|
||||||
{
|
{
|
||||||
filter.InvokeOnRemove(item.Value);
|
filter.InvokeOnRemove(item.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.Clear();
|
dict.Clear();
|
||||||
viewMap.Clear();
|
viewMap.Clear();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace ObservableCollections.Internal
|
|
||||||
{
|
|
||||||
internal class SynchronizedEnumerator<T> : IEnumerator<T>
|
|
||||||
{
|
|
||||||
bool isDisposed;
|
|
||||||
readonly object gate;
|
|
||||||
readonly bool lockTaken;
|
|
||||||
readonly IEnumerator<T> enumerator;
|
|
||||||
|
|
||||||
public SynchronizedEnumerator(object gate, IEnumerator<T> enumerator)
|
|
||||||
{
|
|
||||||
this.gate = gate;
|
|
||||||
this.enumerator = enumerator;
|
|
||||||
Monitor.Enter(gate, ref lockTaken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Current => enumerator.Current;
|
|
||||||
|
|
||||||
object IEnumerator.Current => Current;
|
|
||||||
public bool MoveNext() => enumerator.MoveNext();
|
|
||||||
public void Reset() => enumerator.Reset();
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!isDisposed)
|
|
||||||
{
|
|
||||||
isDisposed = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
enumerator.Dispose();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (lockTaken)
|
|
||||||
{
|
|
||||||
Monitor.Exit(gate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 08405416bc7c7e04e9bcaa4fa13c875f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace ObservableCollections.Internal
|
|
||||||
{
|
|
||||||
internal class SynchronizedViewEnumerator<T, TView> : IEnumerator<(T, TView)>, IDisposable
|
|
||||||
{
|
|
||||||
bool isDisposed;
|
|
||||||
readonly bool lockTaken;
|
|
||||||
readonly object gate;
|
|
||||||
readonly IEnumerator<(T, TView)> enumerator;
|
|
||||||
readonly ISynchronizedViewFilter<T, TView> filter;
|
|
||||||
(T, TView) current;
|
|
||||||
|
|
||||||
public SynchronizedViewEnumerator(object gate, IEnumerator<(T, TView)> enumerator, ISynchronizedViewFilter<T, TView> filter)
|
|
||||||
{
|
|
||||||
this.gate = gate;
|
|
||||||
this.enumerator = enumerator;
|
|
||||||
this.filter = filter;
|
|
||||||
this.current = default;
|
|
||||||
this.isDisposed = false;
|
|
||||||
Monitor.Enter(gate, ref lockTaken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public (T, TView) Current => current;
|
|
||||||
object IEnumerator.Current => Current;
|
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
while (enumerator.MoveNext())
|
|
||||||
{
|
|
||||||
current = enumerator.Current;
|
|
||||||
if (filter.IsMatch(current.Item1, current.Item2))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public void Reset() => throw new NotSupportedException();
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!isDisposed)
|
|
||||||
{
|
|
||||||
isDisposed = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
enumerator.Dispose();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (lockTaken)
|
|
||||||
{
|
|
||||||
Monitor.Exit(gate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 98be7e821cfba26469f0911671fb24b6
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -103,9 +103,17 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(KeyValuePair<TKey, TValue>, TView)> GetEnumerator()
|
public IEnumerator<(KeyValuePair<TKey, TValue>, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<KeyValuePair<TKey, TValue>, TView>(SyncRoot,
|
lock (SyncRoot)
|
||||||
dict.Select(x => (new KeyValuePair<TKey, TValue>(x.Key, x.Value.Item1), x.Value.Item2)).GetEnumerator(),
|
{
|
||||||
filter);
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
var v = (new KeyValuePair<TKey, TValue>(item.Key, item.Value.Item1), item.Value.Item2);
|
||||||
|
if (filter.IsMatch(v.Item1, v.Item2))
|
||||||
|
{
|
||||||
|
yield return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -211,7 +211,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<KeyValuePair<TKey, TValue>>(SyncRoot, dictionary.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in dictionary)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -280,7 +280,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, buffer.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in buffer)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -88,7 +88,16 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, dict.Select(x => x.Value).GetEnumerator(), filter);
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Value.Item1, item.Value.Item2))
|
||||||
|
{
|
||||||
|
yield return item.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
@ -247,7 +247,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, set.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in set)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -90,13 +90,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in list.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, list.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -90,13 +90,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, queue.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in queue)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, queue.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in queue.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +203,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, queue.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in queue)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -91,13 +91,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, ringBuffer.AsEnumerable().GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in ringBuffer)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, ringBuffer.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in ringBuffer.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, buffer.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in buffer)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -90,13 +90,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, stack.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in stack)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, stack.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in stack.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, stack.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in stack)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -67,13 +67,28 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in list.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +162,16 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, array.AsEnumerable().GetEnumerator(), filter);
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in array)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
@ -88,7 +88,16 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, dict.Select(x => x.Value).GetEnumerator(), filter);
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Value.Value, item.Value.View))
|
||||||
|
{
|
||||||
|
yield return item.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
@ -13,7 +13,7 @@ namespace ObservableCollections.Internal
|
|||||||
readonly Func<T, TView> transform;
|
readonly Func<T, TView> transform;
|
||||||
readonly Func<T, TKey> identitySelector;
|
readonly Func<T, TKey> identitySelector;
|
||||||
readonly Dictionary<TKey, TView> viewMap; // view-map needs to use in remove.
|
readonly Dictionary<TKey, TView> viewMap; // view-map needs to use in remove.
|
||||||
readonly SortedDictionary<(TView View, TKey Key), (T Value, TView View)> list;
|
readonly SortedDictionary<(TView View, TKey Key), (T Value, TView View)> dict;
|
||||||
|
|
||||||
ISynchronizedViewFilter<T, TView> filter;
|
ISynchronizedViewFilter<T, TView> filter;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ namespace ObservableCollections.Internal
|
|||||||
dict.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
}
|
}
|
||||||
this.list = dict;
|
this.dict = dict;
|
||||||
this.source.CollectionChanged += SourceCollectionChanged;
|
this.source.CollectionChanged += SourceCollectionChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ namespace ObservableCollections.Internal
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return list.Count;
|
return dict.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ namespace ObservableCollections.Internal
|
|||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
foreach (var (_, (value, view)) in list)
|
foreach (var (_, (value, view)) in dict)
|
||||||
{
|
{
|
||||||
filter.InvokeOnAttach(value, view);
|
filter.InvokeOnAttach(value, view);
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ namespace ObservableCollections.Internal
|
|||||||
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
if (resetAction != null)
|
if (resetAction != null)
|
||||||
{
|
{
|
||||||
foreach (var (_, (value, view)) in list)
|
foreach (var (_, (value, view)) in dict)
|
||||||
{
|
{
|
||||||
resetAction(value, view);
|
resetAction(value, view);
|
||||||
}
|
}
|
||||||
@ -92,7 +92,17 @@ namespace ObservableCollections.Internal
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.Select(x => x.Value).GetEnumerator(), filter);
|
|
||||||
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Value.Value, item.Value.View))
|
||||||
|
{
|
||||||
|
yield return item.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
@ -116,7 +126,7 @@ namespace ObservableCollections.Internal
|
|||||||
var value = e.NewItem;
|
var value = e.NewItem;
|
||||||
var view = transform(value);
|
var view = transform(value);
|
||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
list.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
filter.InvokeOnAdd(value, view);
|
filter.InvokeOnAdd(value, view);
|
||||||
}
|
}
|
||||||
@ -126,7 +136,7 @@ namespace ObservableCollections.Internal
|
|||||||
{
|
{
|
||||||
var view = transform(value);
|
var view = transform(value);
|
||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
list.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
filter.InvokeOnAdd(value, view);
|
filter.InvokeOnAdd(value, view);
|
||||||
}
|
}
|
||||||
@ -141,7 +151,7 @@ namespace ObservableCollections.Internal
|
|||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
if (viewMap.Remove(id, out var view))
|
if (viewMap.Remove(id, out var view))
|
||||||
{
|
{
|
||||||
list.Remove((view, id), out var v);
|
dict.Remove((view, id), out var v);
|
||||||
filter.InvokeOnRemove(v);
|
filter.InvokeOnRemove(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,7 +162,7 @@ namespace ObservableCollections.Internal
|
|||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
if (viewMap.Remove(id, out var view))
|
if (viewMap.Remove(id, out var view))
|
||||||
{
|
{
|
||||||
list.Remove((view, id), out var v);
|
dict.Remove((view, id), out var v);
|
||||||
filter.InvokeOnRemove(v);
|
filter.InvokeOnRemove(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,14 +176,14 @@ namespace ObservableCollections.Internal
|
|||||||
var oldKey = identitySelector(oldValue);
|
var oldKey = identitySelector(oldValue);
|
||||||
if (viewMap.Remove(oldKey, out var oldView))
|
if (viewMap.Remove(oldKey, out var oldView))
|
||||||
{
|
{
|
||||||
list.Remove((oldView, oldKey));
|
dict.Remove((oldView, oldKey));
|
||||||
filter.InvokeOnRemove(oldValue, oldView);
|
filter.InvokeOnRemove(oldValue, oldView);
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = e.NewItem;
|
var value = e.NewItem;
|
||||||
var view = transform(value);
|
var view = transform(value);
|
||||||
var id = identitySelector(value);
|
var id = identitySelector(value);
|
||||||
list.Add((view, id), (value, view));
|
dict.Add((view, id), (value, view));
|
||||||
viewMap.Add(id, view);
|
viewMap.Add(id, view);
|
||||||
|
|
||||||
filter.InvokeOnAdd(value, view);
|
filter.InvokeOnAdd(value, view);
|
||||||
@ -193,12 +203,12 @@ namespace ObservableCollections.Internal
|
|||||||
case NotifyCollectionChangedAction.Reset:
|
case NotifyCollectionChangedAction.Reset:
|
||||||
if (!filter.IsNullFilter())
|
if (!filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
foreach (var item in list)
|
foreach (var item in dict)
|
||||||
{
|
{
|
||||||
filter.InvokeOnRemove(item.Value);
|
filter.InvokeOnRemove(item.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.Clear();
|
dict.Clear();
|
||||||
viewMap.Clear();
|
viewMap.Clear();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace ObservableCollections.Internal
|
|
||||||
{
|
|
||||||
internal class SynchronizedViewEnumerator<T, TView> : IEnumerator<(T, TView)>, IDisposable
|
|
||||||
{
|
|
||||||
bool isDisposed;
|
|
||||||
readonly bool lockTaken;
|
|
||||||
readonly object gate;
|
|
||||||
readonly IEnumerator<(T, TView)> enumerator;
|
|
||||||
readonly ISynchronizedViewFilter<T, TView> filter;
|
|
||||||
(T, TView) current;
|
|
||||||
|
|
||||||
public SynchronizedViewEnumerator(object gate, IEnumerator<(T, TView)> enumerator, ISynchronizedViewFilter<T, TView> filter)
|
|
||||||
{
|
|
||||||
this.gate = gate;
|
|
||||||
this.enumerator = enumerator;
|
|
||||||
this.filter = filter;
|
|
||||||
this.current = default;
|
|
||||||
this.isDisposed = false;
|
|
||||||
Monitor.Enter(gate, ref lockTaken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public (T, TView) Current => current;
|
|
||||||
object IEnumerator.Current => Current!;
|
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
while (enumerator.MoveNext())
|
|
||||||
{
|
|
||||||
current = enumerator.Current;
|
|
||||||
if (filter.IsMatch(current.Item1, current.Item2))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public void Reset() => throw new NotSupportedException();
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!isDisposed)
|
|
||||||
{
|
|
||||||
isDisposed = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
enumerator.Dispose();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (lockTaken)
|
|
||||||
{
|
|
||||||
Monitor.Exit(gate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -103,9 +103,17 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(KeyValuePair<TKey, TValue>, TView)> GetEnumerator()
|
public IEnumerator<(KeyValuePair<TKey, TValue>, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<KeyValuePair<TKey, TValue>, TView>(SyncRoot,
|
lock (SyncRoot)
|
||||||
dict.Select(x => (new KeyValuePair<TKey, TValue>(x.Key, x.Value.Item1), x.Value.Item2)).GetEnumerator(),
|
{
|
||||||
filter);
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
var v = (new KeyValuePair<TKey, TValue>(item.Key, item.Value.Item1), item.Value.Item2);
|
||||||
|
if (filter.IsMatch(v.Item1, v.Item2))
|
||||||
|
{
|
||||||
|
yield return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -88,7 +88,16 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, dict.Select(x => x.Value).GetEnumerator(), filter);
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in dict)
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Value.Item1, item.Value.Item2))
|
||||||
|
{
|
||||||
|
yield return item.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
@ -247,7 +247,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, set.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in set)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
@ -90,13 +90,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, list.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in list.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,13 +90,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, queue.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in queue)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, queue.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in queue.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,13 +91,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, ringBuffer.AsEnumerable().GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in ringBuffer)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, ringBuffer.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in ringBuffer.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,13 +90,28 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<(T, TView)> GetEnumerator()
|
public IEnumerator<(T, TView)> GetEnumerator()
|
||||||
{
|
{
|
||||||
if (!reverse)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, stack.GetEnumerator(), filter);
|
if (!reverse)
|
||||||
}
|
{
|
||||||
else
|
foreach (var item in stack)
|
||||||
{
|
{
|
||||||
return new SynchronizedViewEnumerator<T, TView>(SyncRoot, stack.AsEnumerable().Reverse().GetEnumerator(), filter);
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var item in stack.AsEnumerable().Reverse())
|
||||||
|
{
|
||||||
|
if (filter.IsMatch(item.Item1, item.Item2))
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,13 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public IEnumerator<T> GetEnumerator()
|
public IEnumerator<T> GetEnumerator()
|
||||||
{
|
{
|
||||||
return new SynchronizedEnumerator<T>(SyncRoot, stack.GetEnumerator());
|
lock (SyncRoot)
|
||||||
|
{
|
||||||
|
foreach (var item in stack)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user