/
n-dimens
/
pascalabcnet
Обзор
Документация
Войти
/
n-dimens
/
pascalabcnet
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
ICSharpCode.TextEditor/Src/Util/WeakCollection.cs
136 строк
4 KB
Бондарев Иван
initial commit
14 май 2015, 22:35
14 май 2015, 22:35
e6e67c1
Код
Авторство
О чём код?
// <file> // <copyright see="prj:///doc/copyright.txt"/> // <license see="prj:///doc/license.txt"/> // <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/> // <version>$Revision: 2683 $</version> // </file> using System; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Util { /// <summary> /// A collection that does not allows its elements to be garbage-collected (unless there are other /// references to the elements). Elements will disappear from the collection when they are /// garbage-collected. /// /// The WeakCollection is not thread-safe, not even for read-only access! /// No methods may be called on the WeakCollection while it is enumerated, not even a Contains or /// creating a second enumerator. /// The WeakCollection does not preserve any order among its contents; the ordering may be different each /// time the collection is enumerated. /// /// Since items may disappear at any time when they are garbage collected, this class /// cannot provide a useful implementation for Count and thus cannot implement the ICollection interface. /// </summary> public class WeakCollection<T> : IEnumerable<T> where T : class { readonly List<WeakReference> innerList = new List<WeakReference>(); /// <summary> /// Adds an element to the collection. Runtime: O(n). /// </summary> public void Add(T item) { if (item == null) throw new ArgumentNullException("item"); CheckNoEnumerator(); if (innerList.Count == innerList.Capacity || (innerList.Count % 32) == 31) innerList.RemoveAll(delegate(WeakReference r) { return !r.IsAlive; }); innerList.Add(new WeakReference(item)); } /// <summary> /// Removes all elements from the collection. Runtime: O(n). /// </summary> public void Clear() { innerList.Clear(); CheckNoEnumerator(); } /// <summary> /// Checks if the collection contains an item. Runtime: O(n). /// </summary> public bool Contains(T item) { if (item == null) throw new ArgumentNullException("item"); CheckNoEnumerator(); foreach (T element in this) { if (item.Equals(element)) return true; } return false; } /// <summary> /// Removes an element from the collection. Returns true if the item is found and removed, /// false when the item is not found. /// Runtime: O(n). /// </summary> public bool Remove(T item) { if (item == null) throw new ArgumentNullException("item"); CheckNoEnumerator(); for (int i = 0; i < innerList.Count;) { T element = (T)innerList[i].Target; if (element == null) { RemoveAt(i); } else if (element == item) { RemoveAt(i); return true; } else { i++; } } return false; } void RemoveAt(int i) { int lastIndex = innerList.Count - 1; innerList[i] = innerList[lastIndex]; innerList.RemoveAt(lastIndex); } bool hasEnumerator; void CheckNoEnumerator() { if (hasEnumerator) throw new InvalidOperationException("The WeakCollection is already being enumerated, it cannot be modified at the same time. Ensure you dispose the first enumerator before modifying the WeakCollection."); } /// <summary> /// Enumerates the collection. /// Each MoveNext() call on the enumerator is O(1), thus the enumeration is O(n). /// </summary> public IEnumerator<T> GetEnumerator() { if (hasEnumerator) throw new InvalidOperationException("The WeakCollection is already being enumerated, it cannot be enumerated twice at the same time. Ensure you dispose the first enumerator before using another enumerator."); try { hasEnumerator = true; for (int i = 0; i < innerList.Count;) { T element = (T)innerList[i].Target; if (element == null) { RemoveAt(i); } else { yield return element; i++; } } } finally { hasEnumerator = false; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } }