CompositeDisposable
public sealed class CompositeDisposable : ICollection<IDisposable>, IEnumerable<IDisposable>, IEnumerable, ICancelable, IDisposable
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace System.Reactive.Disposables
{
public sealed class CompositeDisposable : ICollection<IDisposable>, IEnumerable<IDisposable>, IEnumerable, ICancelable, IDisposable
{
private readonly object _gate = new object();
private bool _disposed;
private List<IDisposable> _disposables;
private int _count;
private const int SHRINK_THRESHOLD = 64;
public int Count => _count;
public bool IsReadOnly => false;
public bool IsDisposed => _disposed;
public CompositeDisposable()
{
_disposables = new List<IDisposable>();
}
public CompositeDisposable(int capacity)
{
if (capacity < 0)
throw new ArgumentOutOfRangeException("capacity");
_disposables = new List<IDisposable>(capacity);
}
public CompositeDisposable(params IDisposable[] disposables)
: this((IEnumerable<IDisposable>)disposables)
{
}
public CompositeDisposable(IEnumerable<IDisposable> disposables)
{
if (disposables == null)
throw new ArgumentNullException("disposables");
_disposables = new List<IDisposable>(disposables);
if (_disposables.Contains(null))
throw new ArgumentException(Strings_Core.DISPOSABLES_CANT_CONTAIN_NULL, "disposables");
_count = _disposables.Count;
}
public void Add(IDisposable item)
{
if (item == null)
throw new ArgumentNullException("item");
bool flag = false;
lock (_gate) {
flag = _disposed;
if (!_disposed) {
_disposables.Add(item);
_count++;
}
}
if (flag)
item.Dispose();
}
public bool Remove(IDisposable item)
{
if (item == null)
throw new ArgumentNullException("item");
bool flag = false;
lock (_gate) {
if (!_disposed) {
int num = _disposables.IndexOf(item);
if (num >= 0) {
flag = true;
_disposables[num] = null;
_count--;
if (_disposables.Capacity > 64 && _count < _disposables.Capacity / 2) {
List<IDisposable> disposables = _disposables;
_disposables = new List<IDisposable>(_disposables.Capacity / 2);
foreach (IDisposable item2 in disposables) {
if (item2 != null)
_disposables.Add(item2);
}
}
}
}
}
if (flag)
item.Dispose();
return flag;
}
public void Dispose()
{
IDisposable[] array = null;
lock (_gate) {
if (!_disposed) {
_disposed = true;
array = _disposables.ToArray();
_disposables.Clear();
_count = 0;
}
}
if (array != null) {
IDisposable[] array2 = array;
for (int i = 0; i < array2.Length; i++) {
array2[i]?.Dispose();
}
}
}
public void Clear()
{
IDisposable[] array = null;
lock (_gate) {
array = _disposables.ToArray();
_disposables.Clear();
_count = 0;
}
IDisposable[] array2 = array;
for (int i = 0; i < array2.Length; i++) {
array2[i]?.Dispose();
}
}
public bool Contains(IDisposable item)
{
if (item == null)
throw new ArgumentNullException("item");
lock (_gate) {
return _disposables.Contains(item);
}
}
public void CopyTo(IDisposable[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException("array");
if (arrayIndex < 0 || arrayIndex >= array.Length)
throw new ArgumentOutOfRangeException("arrayIndex");
lock (_gate) {
Array.Copy((from d in _disposables
where d != null
select d).ToArray(), 0, array, arrayIndex, array.Length - arrayIndex);
}
}
public IEnumerator<IDisposable> GetEnumerator()
{
IEnumerable<IDisposable> enumerable = null;
lock (_gate) {
enumerable = (from d in _disposables
where d != null
select d).ToList();
}
return enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}