protected override void Dispose(bool disposing)
        {
            if (disposed)
            {
                string doubleDisposeStack = null;
                if (memoryManager.GenerateCallStacks)
                {
                    doubleDisposeStack = Environment.StackTrace;
                }

                return;
            }

            if (memoryManager.GenerateCallStacks)
            {
                disposeStack = Environment.StackTrace;
            }

            if (disposing)
            {
                // Once this flag is set, we can't access any properties -- use fields directly
                disposed = true;

                memoryManager.ReportStreamDisposed();

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

                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);

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

                RecyclableMemoryStreamManager.Events.Writer.MemoryStreamDoubleDispose(id, tag,
                                                                                      AllocationStack,
                                                                                      DisposeStack,
                                                                                      doubleDisposeStack);
                return;
            }

            RecyclableMemoryStreamManager.Events.Writer.MemoryStreamDisposed(id, tag);

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

            if (disposing)
            {
                memoryManager.ReportStreamDisposed();

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

                RecyclableMemoryStreamManager.Events.Writer.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(disposing);
                    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);
        }