protected override void Dispose(bool disposing)
        {
            if (Interlocked.CompareExchange(ref _disposedState, 1, 0) != 0)
            {
                string doubleDisposeStack = null;
                if (_memoryManager.GenerateCallStacks)
                {
                    doubleDisposeStack = Environment.StackTrace;
                }

                RecyclableMemoryStreamManager.EventsWriter.MemoryStreamDoubleDispose(_id, _tag,
                                                                                     AllocationStack,
                                                                                     DisposeStack,
                                                                                     doubleDisposeStack);
                return;
            }

            RecyclableMemoryStreamManager.EventsWriter.MemoryStreamDisposed(_id, _tag);

            if (_memoryManager.GenerateCallStacks)
            {
                DisposeStack = Environment.StackTrace;
            }

            if (disposing)
            {
                _memoryManager.ReportStreamDisposed();

                GC.SuppressFinalize(this);
            }
            else
            {
                // We're being finalized.

                RecyclableMemoryStreamManager.EventsWriter.MemoryStreamFinalized(_id, _tag, AllocationStack);

#if !NETSTANDARD1_4
                if (AppDomain.CurrentDomain.IsFinalizingForUnload())
                {
                    // If we're being finalized because of a shutdown, don't go any further.
                    // We have no idea what's already been cleaned up. Triggering events may cause
                    // a crash.
                    base.Dispose(false);
                    return;
                }
#endif

                _memoryManager.ReportStreamFinalized();
            }

            _memoryManager.ReportStreamLength(_length);

            if (_largeBuffer != null)
            {
                _memoryManager.ReturnLargeBuffer(_largeBuffer, _tag);
            }

            if (_dirtyBuffers != null)
            {
                foreach (var buffer in _dirtyBuffers)
                {
                    _memoryManager.ReturnLargeBuffer(buffer, _tag);
                }
            }

            _memoryManager.ReturnBlocks(_blocks, _tag);
            _blocks.Clear();

            base.Dispose(disposing);
        }