{"record":{"id":"0bab97fd58190bf2","repo":"dotnet/reactive","slug":"cannot-access-a-disposed-object-object-name","errorCode":null,"errorMessage":"Cannot access a disposed object.\nObject name: ''.","messagePattern":"Cannot access a disposed object\\.\nObject name: ''\\.","errorType":"exception","errorClass":"ObjectDisposedException","httpStatus":null,"severity":"error","filePath":"Ix.NET/Source/System.Interactive/System/Linq/Operators/Memoize.cs","lineNumber":143,"sourceCode":"                : this(source, new MaxRefCountList<T>())\n            {\n            }\n\n            public MemoizedBuffer(IEnumerator<T> source, int readerCount)\n                : this(source, new RefCountList<T>(readerCount))\n            {\n            }\n\n            private MemoizedBuffer(IEnumerator<T> source, IRefCountList<T> buffer)\n            {\n                _source = source;\n                _buffer = buffer;\n            }\n\n            public IEnumerator<T> GetEnumerator()\n            {\n                if (_disposed)\n                    throw new ObjectDisposedException(\"\");\n\n                return GetEnumerator_();\n            }\n\n            IEnumerator IEnumerable.GetEnumerator()\n            {\n                if (_disposed)\n                    throw new ObjectDisposedException(\"\");\n\n                return GetEnumerator();\n            }\n\n            public void Dispose()\n            {\n                lock (_gate)\n                {\n                    if (!_disposed)\n                    {","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Ix.NET/Source/System.Interactive/System/Linq/Operators/Memoize.cs#L125-L161","documentation":"MemoizedBuffer.GetEnumerator checks the buffer's _disposed flag and throws ObjectDisposedException once Dispose() has been called on the buffer. After disposal, new enumerators can no longer be handed out, so requesting one throws \"Cannot access a disposed object\".","triggerScenarios":"Calling GetEnumerator() on the IBuffer returned by Memoize after the buffer (or all of its leases) has been disposed — e.g. enumerating the buffer after a using block over the buffer ended, or after the owning scope disposed it.","commonSituations":"Storing the IBuffer in a field or cache while disposing it in a using statement; concurrent consumers starting enumeration after the producer disposed the buffer; returning the buffer from a method that disposes it before the caller enumerates.","solutions":["Keep the buffer alive (dispose it) only after all consumers have finished enumerating.","Obtain all enumerators inside the lifetime of the buffer's using block.","If lazy consumption is needed, materialize with ToList/ToArray before disposing."],"exampleFix":"// before\nIBuffer<int> buffer;\nusing (buffer = source.Memoize()) { }\nforeach (var x in buffer) { } // throws\n// after\nusing (var buffer = source.Memoize())\n{\n    foreach (var x in buffer) { }\n}","handlingStrategy":"try-catch","validationCode":"bool usable = buffer is IBuffer<T> b && !IsDisposed(b); // track disposal via your own flag since _disposed is private\nif (!usable) { /* re-memoize or fail fast */ }","typeGuard":"static bool CanEnumerate<T>(IBuffer<T> buffer, HashSet<object> disposed) => !disposed.Contains(buffer);","tryCatchPattern":"try { foreach (var x in buffer) Process(x); }\ncatch (ObjectDisposedException) { buffer = source.Memoize(); foreach (var x in buffer) Process(x); }","preventionTips":["Scope buffer disposal so it encloses all enumeration","Never cache an IBuffer beyond its using block","Materialize with ToList/ToArray before disposal if late reads are needed"],"tags":["object-disposed","memoize","ix-interactive","linq"],"backgroundTag":"invalid-state-transition","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}