CompositeDisposable
                    public sealed class CompositeDisposable : ICollection<IDisposable>, IEnumerable<IDisposable>, IEnumerable, ICancelable, IDisposable
                
                Represents a group of disposable resources that are disposed together.
            
                using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
namespace System.Reactive.Disposables
{
    [System.Runtime.CompilerServices.NullableContext(1)]
    [System.Runtime.CompilerServices.Nullable(0)]
    public sealed class CompositeDisposable : ICollection<IDisposable>, IEnumerable<IDisposable>, IEnumerable, ICancelable, IDisposable
    {
        [System.Runtime.CompilerServices.Nullable(0)]
        private sealed class CompositeEnumerator : IEnumerator<IDisposable>, IEnumerator, IDisposable
        {
            [System.Runtime.CompilerServices.Nullable(new byte[] {
                1,
                2
            })]
            private readonly IDisposable[] _disposables;
            private int _index;
            public IDisposable Current => _disposables[_index];
            object IEnumerator.Current {
                get {
                    return _disposables[_index];
                }
            }
            public CompositeEnumerator([System.Runtime.CompilerServices.Nullable(new byte[] {
                1,
                2
            })] IDisposable[] disposables)
            {
                _disposables = disposables;
                _index = -1;
            }
            public void Dispose()
            {
                IDisposable[] disposables = _disposables;
                Array.Clear(disposables, 0, disposables.Length);
            }
            public bool MoveNext()
            {
                IDisposable[] disposables = _disposables;
                int num;
                do {
                    num = ++_index;
                    if (num >= disposables.Length)
                        return false;
                } while (disposables[num] == null);
                return true;
            }
            public void Reset()
            {
                _index = -1;
            }
        }
        private readonly object _gate = new object();
        private bool _disposed;
        [System.Runtime.CompilerServices.Nullable(new byte[] {
            1,
            2
        })]
        private List<IDisposable> _disposables;
        private int _count;
        private const int ShrinkThreshold = 64;
        private const int DefaultCapacity = 16;
        private static readonly CompositeEnumerator EmptyEnumerator = new CompositeEnumerator(Array.Empty<IDisposable>());
        public int Count => Volatile.Read(ref _count);
        public bool IsReadOnly => false;
        public bool IsDisposed => Volatile.Read(ref _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)
        {
            if (disposables == null)
                throw new ArgumentNullException("disposables");
            _disposables = ToList(disposables);
            Volatile.Write(ref _count, _disposables.Count);
        }
        public CompositeDisposable(IEnumerable<IDisposable> disposables)
        {
            if (disposables == null)
                throw new ArgumentNullException("disposables");
            _disposables = ToList(disposables);
            Volatile.Write(ref _count, _disposables.Count);
        }
        [return: System.Runtime.CompilerServices.Nullable(new byte[] {
            1,
            2
        })]
        private static List<IDisposable> ToList(IEnumerable<IDisposable> disposables)
        {
            IDisposable[] array = disposables as IDisposable[];
            int capacity;
            if (array == null) {
                ICollection<IDisposable> collection = disposables as ICollection<IDisposable>;
                capacity = ((collection == null) ? 16 : collection.Count);
            } else
                capacity = array.Length;
            List<IDisposable> list = new List<IDisposable>(capacity);
            foreach (IDisposable disposable in disposables) {
                if (disposable == null)
                    throw new ArgumentException(Strings_Core.DISPOSABLES_CANT_CONTAIN_NULL, "disposables");
                list.Add(disposable);
            }
            return list;
        }
        public void Add(IDisposable item)
        {
            if (item == null)
                throw new ArgumentNullException("item");
            lock (_gate) {
                if (!_disposed) {
                    _disposables.Add(item);
                    Volatile.Write(ref _count, _count + 1);
                    return;
                }
            }
            item.Dispose();
        }
        public bool Remove(IDisposable item)
        {
            if (item == null)
                throw new ArgumentNullException("item");
            lock (_gate) {
                if (_disposed)
                    return false;
                List<IDisposable> disposables = _disposables;
                int num = disposables.IndexOf(item);
                if (num < 0)
                    return false;
                disposables[num] = null;
                if (disposables.Capacity > 64 && _count < disposables.Capacity / 2) {
                    List<IDisposable> list = new List<IDisposable>(disposables.Capacity / 2);
                    foreach (IDisposable item2 in disposables) {
                        if (item2 != null)
                            list.Add(item2);
                    }
                    _disposables = list;
                }
                Volatile.Write(ref _count, _count - 1);
            }
            item.Dispose();
            return true;
        }
        public void Dispose()
        {
            List<IDisposable> list = null;
            lock (_gate) {
                if (!_disposed) {
                    list = _disposables;
                    _disposables = null;
                    Volatile.Write(ref _count, 0);
                    Volatile.Write(ref _disposed, true);
                }
            }
            if (list != null) {
                foreach (IDisposable item in list) {
                    item?.Dispose();
                }
            }
        }
        public void Clear()
        {
            IDisposable[] array = default(IDisposable[]);
            lock (_gate) {
                if (_disposed)
                    return;
                List<IDisposable> disposables = _disposables;
                array = disposables.ToArray();
                disposables.Clear();
                Volatile.Write(ref _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) {
                if (!_disposed)
                    return _disposables.Contains(item);
                return false;
            }
        }
        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) {
                if (!_disposed) {
                    if (arrayIndex + _count > array.Length)
                        throw new ArgumentOutOfRangeException("arrayIndex");
                    int num = arrayIndex;
                    foreach (IDisposable disposable in _disposables) {
                        if (disposable != null)
                            array[num++] = disposable;
                    }
                }
            }
        }
        public IEnumerator<IDisposable> GetEnumerator()
        {
            lock (_gate) {
                if (!_disposed && _count != 0)
                    return new CompositeEnumerator(_disposables.ToArray());
                return EmptyEnumerator;
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}