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.Linq;
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;
        private object _disposables;
        private int _count;
        private const int ShrinkThreshold = 64;
        private const int MaximumLinearSearchThreshold = 1024;
        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");
            (object, int) valueTuple = ToListOrDictionary(disposables);
            _disposables = valueTuple.Item1;
            Volatile.Write(ref _count, disposables.Length);
        }
        public CompositeDisposable(IEnumerable<IDisposable> disposables)
        {
            if (disposables == null)
                throw new ArgumentNullException("disposables");
            (object, int) valueTuple = ToListOrDictionary(disposables);
            _disposables = valueTuple.Item1;
            int item = valueTuple.Item2;
            Volatile.Write(ref _count, item);
        }
        [return: System.Runtime.CompilerServices.Nullable(new byte[] {
            0,
            1
        })]
        private static (object Collection, int Count) ToListOrDictionary(IEnumerable<IDisposable> disposables)
        {
            IDisposable[] array = disposables as IDisposable[];
            int num;
            if (array == null) {
                ICollection<IDisposable> collection = disposables as ICollection<IDisposable>;
                num = ((collection == null) ? 16 : collection.Count);
            } else
                num = array.Length;
            int num2 = num;
            if (num2 > 1024) {
                Dictionary<IDisposable, int> dictionary = new Dictionary<IDisposable, int>(num2);
                int num3 = 0;
                foreach (IDisposable disposable in disposables) {
                    if (disposable == null)
                        throw new ArgumentException(Strings_Core.DISPOSABLES_CANT_CONTAIN_NULL, "disposables");
                    dictionary.TryGetValue(disposable, out int value);
                    dictionary[disposable] = value + 1;
                    num3++;
                }
                return (dictionary, num3);
            }
            List<IDisposable> list = new List<IDisposable>(num2);
            foreach (IDisposable disposable2 in disposables) {
                if (disposable2 == null)
                    throw new ArgumentException(Strings_Core.DISPOSABLES_CANT_CONTAIN_NULL, "disposables");
                list.Add(disposable2);
            }
            int count = list.Count;
            return (list, list.Count);
        }
        public void Add(IDisposable item)
        {
            if (item == null)
                throw new ArgumentNullException("item");
            lock (_gate) {
                if (!_disposed) {
                    List<IDisposable> list = _disposables as List<IDisposable>;
                    if (list != null) {
                        list.Add(item);
                        if (list.Count > 1024) {
                            Dictionary<IDisposable, int> dictionary = new Dictionary<IDisposable, int>(list.Count + list.Count / 4);
                            foreach (IDisposable item2 in list) {
                                if (item2 != null) {
                                    dictionary.TryGetValue(item2, out int value);
                                    dictionary[item2] = value + 1;
                                }
                            }
                            _disposables = dictionary;
                        }
                    } else {
                        Dictionary<IDisposable, int> obj = (Dictionary<IDisposable, int>)_disposables;
                        obj.TryGetValue(item, out int value2);
                        obj[item] = value2 + 1;
                    }
                    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> list = _disposables as List<IDisposable>;
                if (list != null) {
                    int num = list.IndexOf(item);
                    if (num < 0)
                        return false;
                    list[num] = null;
                    if (list.Capacity > 64 && _count < list.Capacity / 2) {
                        List<IDisposable> list2 = new List<IDisposable>(list.Capacity / 2);
                        foreach (IDisposable item2 in list) {
                            if (item2 != null)
                                list2.Add(item2);
                        }
                        _disposables = list2;
                    }
                } else {
                    Dictionary<IDisposable, int> dictionary = (Dictionary<IDisposable, int>)_disposables;
                    if (!dictionary.TryGetValue(item, out int value))
                        return false;
                    value--;
                    if (value == 0)
                        dictionary.Remove(item);
                    else
                        dictionary[item] = value;
                }
                Volatile.Write(ref _count, _count - 1);
            }
            item.Dispose();
            return true;
        }
        public void Dispose()
        {
            List<IDisposable> list = null;
            Dictionary<IDisposable, int> dictionary = null;
            lock (_gate) {
                if (!_disposed) {
                    list = (_disposables as List<IDisposable>);
                    dictionary = (_disposables as Dictionary<IDisposable, int>);
                    _disposables = null;
                    Volatile.Write(ref _count, 0);
                    Volatile.Write(ref _disposed, true);
                }
            }
            if (list != null) {
                foreach (IDisposable item in list) {
                    item?.Dispose();
                }
            }
            if (dictionary != null) {
                foreach (KeyValuePair<IDisposable, int> item2 in dictionary) {
                    item2.Key.Dispose();
                }
            }
        }
        public void Clear()
        {
            IDisposable[] array = default(IDisposable[]);
            lock (_gate) {
                if (_disposed)
                    return;
                object disposables = _disposables;
                List<IDisposable> list = disposables as List<IDisposable>;
                if (list != null) {
                    array = list.ToArray();
                    list.Clear();
                } else {
                    Dictionary<IDisposable, int> obj = (Dictionary<IDisposable, int>)disposables;
                    array = new IDisposable[obj.Count];
                    obj.Keys.CopyTo(array, 0);
                    obj.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) {
                    object disposables = _disposables;
                    return (disposables as List<IDisposable>)?.Contains(item) ?? ((Dictionary<IDisposable, int>)disposables).ContainsKey(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;
                    object disposables = _disposables;
                    List<IDisposable> list = disposables as List<IDisposable>;
                    if (list != null) {
                        foreach (IDisposable item in list) {
                            if (item != null)
                                array[num++] = item;
                        }
                    } else {
                        foreach (KeyValuePair<IDisposable, int> item2 in (Dictionary<IDisposable, int>)disposables) {
                            for (int i = 0; i < item2.Value; i++) {
                                array[num++] = item2.Key;
                            }
                        }
                    }
                }
            }
        }
        public IEnumerator<IDisposable> GetEnumerator()
        {
            lock (_gate) {
                if (!_disposed && _count != 0) {
                    object disposables = _disposables;
                    List<IDisposable> list = disposables as List<IDisposable>;
                    return new CompositeEnumerator((list != null) ? list.ToArray() : ((Dictionary<IDisposable, int>)disposables).Keys.ToArray());
                }
                return EmptyEnumerator;
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}