search
csharp star Featured

Fix: InvalidOperationException error C#

Learn how to fix the InvalidOperationException error in C# applications. This comprehensive guide covers collection modification, enumeration issues, and proper state management techniques.

person By Gautam Sharma
calendar_today January 8, 2026
schedule 25 min read
C# InvalidOperationException Error Collection Enumeration State LINQ

The ‘InvalidOperationException’ is a common C# runtime error that occurs when an operation is performed on an object in a state where the operation is not valid. This error typically happens when trying to modify collections during enumeration, performing operations on disposed objects, calling methods in inappropriate states, or using LINQ operations incorrectly. The error can be challenging to debug because it often occurs in seemingly valid code when the object’s internal state doesn’t support the requested operation.

This comprehensive guide explains what causes this error, why it happens, and provides multiple solutions to fix it in your C# projects with clean code examples and directory structure.


What is the InvalidOperationException?

The InvalidOperationException occurs when:

  • Modifying a collection while iterating over it
  • Performing operations on disposed objects
  • Calling methods when the object is in an invalid state
  • Using LINQ operations incorrectly
  • Accessing properties or methods when the object state doesn’t allow it
  • Performing operations on collections that don’t support the operation

Common Error Messages:

  • System.InvalidOperationException: Collection was modified; enumeration operation may not execute
  • System.InvalidOperationException: Sequence contains no elements
  • System.InvalidOperationException: Operation is not valid due to the current state of the object
  • System.InvalidOperationException: The operation cannot be completed because the object has been disposed
  • System.InvalidOperationException: Enumeration has either not started or has already finished

Understanding the Problem

The InvalidOperationException is a runtime exception that indicates an operation was attempted on an object when the object’s state did not allow the operation to proceed. This error commonly occurs with collections, iterators, and objects that have specific state requirements for their operations. Understanding the object’s state and the conditions under which operations are valid is crucial for preventing this error.

Typical C# Project Structure:

MyCSharpApp/
├── MyCSharpApp.sln
├── src/
│   ├── MyCSharpApp/
│   │   ├── Program.cs
│   │   ├── Controllers/
│   │   │   ├── HomeController.cs
│   │   │   └── DataController.cs
│   │   ├── Models/
│   │   │   ├── DataModel.cs
│   │   │   └── CollectionProcessor.cs
│   │   ├── Services/
│   │   │   ├── CollectionService.cs
│   │   │   └── StateService.cs
│   │   ├── Utilities/
│   │   │   └── CollectionHelper.cs
│   │   ├── MyCSharpApp.csproj
│   │   └── appsettings.json
│   └── MyCSharpApp.Tests/
│       ├── UnitTests.cs
│       └── MyCSharpApp.Tests.csproj
├── packages/
└── bin/

Solution 1: Proper Collection Modification During Iteration

The most common cause of InvalidOperationException is modifying a collection while iterating over it.

❌ Without Proper Collection Handling:

// Services/CollectionService.cs - ❌ Modifying collection during iteration
public class CollectionService
{
    public void RemoveEvenNumbers(List<int> numbers)
    {
        // ❌ Error: Collection was modified; enumeration operation may not execute
        foreach (var number in numbers)
        {
            if (number % 2 == 0)
            {
                numbers.Remove(number); // ❌ This will cause InvalidOperationException
            }
        }
    }
}

✅ With Proper Collection Handling:

Services/CollectionService.cs:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCSharpApp.Services
{
    public interface ICollectionService
    {
        void RemoveEvenNumbers(List<int> numbers);
        List<int> GetFilteredNumbers(List<int> numbers, Func<int, bool> predicate);
        void ProcessCollectionWhileModifying(List<int> numbers);
        List<string> TransformAndFilter(List<string> items, Func<string, bool> filter, Func<string, string> transform);
    }

    public class CollectionService : ICollectionService
    {
        public void RemoveEvenNumbers(List<int> numbers)
        {
            // ✅ Create a copy of the collection to iterate over
            var numbersToRemove = new List<int>();
            
            foreach (var number in numbers)
            {
                if (number % 2 == 0)
                {
                    numbersToRemove.Add(number);
                }
            }
            
            // ✅ Remove items from the original collection
            foreach (var number in numbersToRemove)
            {
                numbers.Remove(number);
            }
        }

        public List<int> GetFilteredNumbers(List<int> numbers, Func<int, bool> predicate)
        {
            // ✅ Use LINQ to create a new collection instead of modifying the original
            return numbers.Where(predicate).ToList();
        }

        public void ProcessCollectionWhileModifying(List<int> numbers)
        {
            // ✅ Use for loop with index to safely modify collection
            for (int i = numbers.Count - 1; i >= 0; i--)
            {
                if (numbers[i] % 2 == 0)
                {
                    numbers.RemoveAt(i);
                }
            }
        }

        public List<string> TransformAndFilter(List<string> items, Func<string, bool> filter, Func<string, string> transform)
        {
            // ✅ Use LINQ to avoid modifying during iteration
            return items
                .Where(filter)
                .Select(transform)
                .ToList();
        }

        // ✅ Method to safely add items during iteration
        public void AddItemsSafely(List<int> source, List<int> target, Func<int, bool> condition)
        {
            // ✅ Iterate over a copy to avoid modification during iteration
            var itemsToAdd = source.Where(condition).ToList();
            
            foreach (var item in itemsToAdd)
            {
                target.Add(item);
            }
        }

        // ✅ Method to safely remove items using LINQ
        public void RemoveItemsSafely<T>(List<T> collection, Func<T, bool> predicate)
        {
            // ✅ Use RemoveAll which is designed for this purpose
            collection.RemoveAll(predicate);
        }

        // ✅ Method to safely update items during iteration
        public void UpdateItemsSafely(List<int> numbers, Func<int, int> updateFunction)
        {
            // ✅ Use for loop to safely update items
            for (int i = 0; i < numbers.Count; i++)
            {
                numbers[i] = updateFunction(numbers[i]);
            }
        }

        // ✅ Method to safely work with dictionary during iteration
        public void ProcessDictionarySafely(Dictionary<string, int> dictionary, Func<string, int, bool> removeCondition)
        {
            // ✅ Collect keys to remove first
            var keysToRemove = new List<string>();
            
            foreach (var kvp in dictionary)
            {
                if (removeCondition(kvp.Key, kvp.Value))
                {
                    keysToRemove.Add(kvp.Key);
                }
            }
            
            // ✅ Remove collected keys
            foreach (var key in keysToRemove)
            {
                dictionary.Remove(key);
            }
        }

        // ✅ Method to safely work with HashSet during iteration
        public void ProcessHashSetSafely(HashSet<int> hashSet, Func<int, bool> removeCondition)
        {
            // ✅ Create a copy to iterate over
            var itemsToRemove = hashSet.Where(removeCondition).ToList();
            
            foreach (var item in itemsToRemove)
            {
                hashSet.Remove(item);
            }
        }
    }
}

Solution 2: Handle LINQ Operations Safely

Prevent InvalidOperationException when using LINQ methods that expect elements to exist.

Utilities/CollectionHelper.cs:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCSharpApp.Utilities
{
    public static class CollectionHelper
    {
        // ✅ Safe First() operation
        public static T SafeFirst<T>(IEnumerable<T> source, T defaultValue = default(T))
        {
            if (source == null || !source.Any())
            {
                return defaultValue;
            }
            
            return source.First();
        }

        // ✅ Safe FirstOrDefault() operation
        public static T SafeFirstOrDefault<T>(IEnumerable<T> source, T defaultValue = default(T))
        {
            if (source == null)
            {
                return defaultValue;
            }
            
            return source.FirstOrDefault();
        }

        // ✅ Safe Single() operation
        public static T SafeSingle<T>(IEnumerable<T> source, T defaultValue = default(T))
        {
            if (source == null || !source.Any())
            {
                return defaultValue;
            }
            
            if (source.Count() > 1)
            {
                throw new InvalidOperationException("Sequence contains more than one element");
            }
            
            return source.First();
        }

        // ✅ Safe SingleOrDefault() operation
        public static T SafeSingleOrDefault<T>(IEnumerable<T> source, T defaultValue = default(T))
        {
            if (source == null)
            {
                return defaultValue;
            }
            
            var count = source.Count();
            if (count == 0)
            {
                return defaultValue;
            }
            
            if (count > 1)
            {
                throw new InvalidOperationException("Sequence contains more than one element");
            }
            
            return source.First();
        }

        // ✅ Safe Last() operation
        public static T SafeLast<T>(IEnumerable<T> source, T defaultValue = default(T))
        {
            if (source == null || !source.Any())
            {
                return defaultValue;
            }
            
            return source.Last();
        }

        // ✅ Safe LastOrDefault() operation
        public static T SafeLastOrDefault<T>(IEnumerable<T> source, T defaultValue = default(T))
        {
            if (source == null)
            {
                return defaultValue;
            }
            
            return source.LastOrDefault();
        }

        // ✅ Safe ElementAt() operation
        public static T SafeElementAt<T>(IEnumerable<T> source, int index, T defaultValue = default(T))
        {
            if (source == null || index < 0 || index >= source.Count())
            {
                return defaultValue;
            }
            
            return source.ElementAt(index);
        }

        // ✅ Safe ElementAtOrDefault() operation
        public static T SafeElementAtOrDefault<T>(IEnumerable<T> source, int index, T defaultValue = default(T))
        {
            if (source == null || index < 0)
            {
                return defaultValue;
            }
            
            return source.ElementAtOrDefault(index);
        }

        // ✅ Safe Aggregate() operation
        public static TAccumulate SafeAggregate<TSource, TAccumulate>(
            IEnumerable<TSource> source,
            TAccumulate seed,
            Func<TAccumulate, TSource, TAccumulate> func)
        {
            if (source == null)
            {
                return seed;
            }
            
            return source.Aggregate(seed, func);
        }

        // ✅ Safe Min() operation
        public static T SafeMin<T>(IEnumerable<T> source, T defaultValue = default(T)) where T : IComparable<T>
        {
            if (source == null || !source.Any())
            {
                return defaultValue;
            }
            
            return source.Min();
        }

        // ✅ Safe Max() operation
        public static T SafeMax<T>(IEnumerable<T> source, T defaultValue = default(T)) where T : IComparable<T>
        {
            if (source == null || !source.Any())
            {
                return defaultValue;
            }
            
            return source.Max();
        }

        // ✅ Safe Average() operation
        public static double SafeAverage(IEnumerable<int> source, double defaultValue = 0)
        {
            if (source == null || !source.Any())
            {
                return defaultValue;
            }
            
            return source.Average();
        }

        // ✅ Safe conversion to list with null check
        public static List<T> SafeToList<T>(IEnumerable<T> source)
        {
            if (source == null)
            {
                return new List<T>();
            }
            
            return source.ToList();
        }

        // ✅ Safe conversion to array with null check
        public static T[] SafeToArray<T>(IEnumerable<T> source)
        {
            if (source == null)
            {
                return new T[0];
            }
            
            return source.ToArray();
        }

        // ✅ Safe Count() with null check
        public static int SafeCount<T>(IEnumerable<T> source)
        {
            if (source == null)
            {
                return 0;
            }
            
            return source.Count();
        }

        // ✅ Safe Any() with null check
        public static bool SafeAny<T>(IEnumerable<T> source, Func<T, bool> predicate = null)
        {
            if (source == null)
            {
                return false;
            }
            
            return predicate == null ? source.Any() : source.Any(predicate);
        }
    }
}

Solution 3: Proper State Management

Ensure objects are in the correct state before performing operations.

Models/CollectionProcessor.cs:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCSharpApp.Models
{
    public class CollectionProcessor<T>
    {
        private List<T> _items;
        private bool _disposed = false;
        private bool _isProcessing = false;

        public CollectionProcessor()
        {
            _items = new List<T>();
        }

        public int Count => _items.Count;
        public bool IsDisposed => _disposed;
        public bool IsProcessing => _isProcessing;

        // ✅ Check if object is disposed before operations
        private void ThrowIfDisposed()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().Name, "Object has been disposed");
            }
        }

        // ✅ Check if object is in valid state for operation
        private void ThrowIfInvalidState()
        {
            if (_isProcessing)
            {
                throw new InvalidOperationException("Operation cannot be performed while processing is in progress");
            }
        }

        // ✅ Add item with state validation
        public void Add(T item)
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            _items.Add(item);
        }

        // ✅ Remove item with state validation
        public bool Remove(T item)
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            return _items.Remove(item);
        }

        // ✅ Process items with proper state management
        public void ProcessItems(Action<T> processor)
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            try
            {
                _isProcessing = true;
                
                // ✅ Create a copy to avoid modification during iteration
                var itemsCopy = new List<T>(_items);
                
                foreach (var item in itemsCopy)
                {
                    processor(item);
                }
            }
            finally
            {
                _isProcessing = false;
            }
        }

        // ✅ Process items with transformation
        public List<TResult> ProcessItems<TResult>(Func<T, TResult> transformer)
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            try
            {
                _isProcessing = true;
                
                var results = new List<TResult>();
                foreach (var item in _items)
                {
                    results.Add(transformer(item));
                }
                
                return results;
            }
            finally
            {
                _isProcessing = false;
            }
        }

        // ✅ Filter items safely
        public List<T> FilterItems(Func<T, bool> predicate)
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            return _items.Where(predicate).ToList();
        }

        // ✅ Clear with state validation
        public void Clear()
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            _items.Clear();
        }

        // ✅ Get items safely
        public List<T> GetItems()
        {
            ThrowIfDisposed();
            
            return new List<T>(_items);
        }

        // ✅ Get item by index safely
        public T GetItem(int index)
        {
            ThrowIfDisposed();
            
            if (index < 0 || index >= _items.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            
            return _items[index];
        }

        // ✅ Set item by index safely
        public void SetItem(int index, T value)
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            if (index < 0 || index >= _items.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }
            
            _items[index] = value;
        }

        // ✅ Enumerate safely
        public IEnumerator<T> GetEnumerator()
        {
            ThrowIfDisposed();
            
            // ✅ Return a copy to prevent modification during enumeration
            return new List<T>(_items).GetEnumerator();
        }

        // ✅ Safe foreach implementation
        public void ForEach(Action<T> action)
        {
            ThrowIfDisposed();
            ThrowIfInvalidState();
            
            // ✅ Use a copy to prevent modification during iteration
            var itemsCopy = new List<T>(_items);
            foreach (var item in itemsCopy)
            {
                action(item);
            }
        }

        // ✅ Dispose pattern implementation
        public void Dispose()
        {
            if (!_disposed)
            {
                _items.Clear();
                _items = null;
                _disposed = true;
            }
        }

        // ✅ Finalizer
        ~CollectionProcessor()
        {
            Dispose();
        }

        // ✅ Reset state
        public void Reset()
        {
            ThrowIfDisposed();
            
            if (_isProcessing)
            {
                throw new InvalidOperationException("Cannot reset while processing is in progress");
            }
            
            _items.Clear();
        }

        // ✅ Begin processing
        public void BeginProcessing()
        {
            ThrowIfDisposed();
            
            if (_isProcessing)
            {
                throw new InvalidOperationException("Processing is already in progress");
            }
            
            _isProcessing = true;
        }

        // ✅ End processing
        public void EndProcessing()
        {
            ThrowIfDisposed();
            
            if (!_isProcessing)
            {
                throw new InvalidOperationException("Processing is not in progress");
            }
            
            _isProcessing = false;
        }
    }
}

Solution 4: Handle Disposed Objects Properly

Properly manage object lifecycles and handle disposed objects gracefully.

Services/StateService.cs:

using System;
using System.Collections.Generic;
using System.IO;

namespace MyCSharpApp.Services
{
    public interface IStateService : IDisposable
    {
        void Initialize();
        void ProcessData(string data);
        string GetData();
        bool IsInitialized { get; }
        bool IsDisposed { get; }
    }

    public class StateService : IStateService
    {
        private List<string> _data;
        private bool _isInitialized = false;
        private bool _disposed = false;
        private readonly object _lock = new object();

        public bool IsInitialized => _isInitialized;
        public bool IsDisposed => _disposed;

        public void Initialize()
        {
            lock (_lock)
            {
                ThrowIfDisposed();
                
                if (_isInitialized)
                {
                    throw new InvalidOperationException("Service is already initialized");
                }
                
                _data = new List<string>();
                _isInitialized = true;
            }
        }

        public void ProcessData(string data)
        {
            lock (_lock)
            {
                ThrowIfDisposed();
                
                if (!_isInitialized)
                {
                    throw new InvalidOperationException("Service is not initialized");
                }
                
                if (string.IsNullOrEmpty(data))
                {
                    throw new ArgumentException("Data cannot be null or empty", nameof(data));
                }
                
                _data.Add(data);
            }
        }

        public string GetData()
        {
            lock (_lock)
            {
                ThrowIfDisposed();
                
                if (!_isInitialized)
                {
                    throw new InvalidOperationException("Service is not initialized");
                }
                
                if (_data == null || _data.Count == 0)
                {
                    return string.Empty;
                }
                
                return string.Join(", ", _data);
            }
        }

        public List<string> GetAllData()
        {
            lock (_lock)
            {
                ThrowIfDisposed();
                
                if (!_isInitialized)
                {
                    throw new InvalidOperationException("Service is not initialized");
                }
                
                // ✅ Return a copy to prevent external modification
                return _data != null ? new List<string>(_data) : new List<string>();
            }
        }

        // ✅ Safe method to check if service can be used
        public bool CanProcessData()
        {
            lock (_lock)
            {
                return !_disposed && _isInitialized;
            }
        }

        // ✅ Safe method to initialize if not already initialized
        public void InitializeIfNot()
        {
            lock (_lock)
            {
                if (!_disposed && !_isInitialized)
                {
                    Initialize();
                }
            }
        }

        // ✅ Method to safely dispose and reinitialize
        public void Recreate()
        {
            lock (_lock)
            {
                if (!_disposed)
                {
                    Dispose();
                }
                
                _disposed = false;
                _isInitialized = false;
                Initialize();
            }
        }

        // ✅ Check if object is disposed
        private void ThrowIfDisposed()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().Name, "Service has been disposed");
            }
        }

        // ✅ Dispose implementation
        public void Dispose()
        {
            lock (_lock)
            {
                if (!_disposed)
                {
                    _data?.Clear();
                    _data = null;
                    _disposed = true;
                }
            }
        }

        // ✅ Finalizer
        ~StateService()
        {
            Dispose();
        }

        // ✅ Safe method to get data count
        public int GetDataCount()
        {
            lock (_lock)
            {
                ThrowIfDisposed();
                
                if (!_isInitialized)
                {
                    throw new InvalidOperationException("Service is not initialized");
                }
                
                return _data?.Count ?? 0;
            }
        }

        // ✅ Safe method to clear data
        public void ClearData()
        {
            lock (_lock)
            {
                ThrowIfDisposed();
                
                if (!_isInitialized)
                {
                    throw new InvalidOperationException("Service is not initialized");
                }
                
                _data?.Clear();
            }
        }
    }
}

Solution 5: Handle Enumerator State Properly

Properly manage enumerator state to prevent InvalidOperationException.

Utilities/EnumeratorHelper.cs:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCSharpApp.Utilities
{
    public static class EnumeratorHelper
    {
        // ✅ Safe enumeration with proper state management
        public static List<T> SafeEnumerate<T>(IEnumerable<T> source)
        {
            if (source == null)
            {
                return new List<T>();
            }
            
            var result = new List<T>();
            
            using (var enumerator = source.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    result.Add(enumerator.Current);
                }
            }
            
            return result;
        }

        // ✅ Safe foreach with exception handling
        public static void SafeForEach<T>(IEnumerable<T> source, Action<T> action)
        {
            if (source == null || action == null)
            {
                return;
            }
            
            try
            {
                foreach (var item in source)
                {
                    action(item);
                }
            }
            catch (InvalidOperationException)
            {
                // ✅ Handle the case where collection was modified during iteration
                // In this case, we could retry with a snapshot
                var snapshot = source.ToList();
                foreach (var item in snapshot)
                {
                    action(item);
                }
            }
        }

        // ✅ Safe aggregation with enumerator
        public static TAccumulate SafeAggregate<T, TAccumulate>(
            IEnumerable<T> source,
            TAccumulate seed,
            Func<TAccumulate, T, TAccumulate> func)
        {
            if (source == null || func == null)
            {
                return seed;
            }
            
            var result = seed;
            
            try
            {
                foreach (var item in source)
                {
                    result = func(result, item);
                }
            }
            catch (InvalidOperationException)
            {
                // ✅ Handle collection modification during iteration
                var snapshot = source.ToList();
                foreach (var item in snapshot)
                {
                    result = func(result, item);
                }
            }
            
            return result;
        }

        // ✅ Safe conversion with error handling
        public static List<T> SafeToListWithErrorHandling<T>(IEnumerable<T> source)
        {
            if (source == null)
            {
                return new List<T>();
            }
            
            try
            {
                return source.ToList();
            }
            catch (InvalidOperationException)
            {
                // ✅ If enumeration fails, create a snapshot first
                var snapshot = new List<T>();
                foreach (var item in source)
                {
                    snapshot.Add(item);
                }
                return snapshot;
            }
        }

        // ✅ Safe where operation with snapshot
        public static List<T> SafeWhere<T>(IEnumerable<T> source, Func<T, bool> predicate)
        {
            if (source == null || predicate == null)
            {
                return new List<T>();
            }
            
            try
            {
                return source.Where(predicate).ToList();
            }
            catch (InvalidOperationException)
            {
                // ✅ If enumeration fails, work with a snapshot
                var snapshot = source.ToList();
                return snapshot.Where(predicate).ToList();
            }
        }

        // ✅ Safe select operation with snapshot
        public static List<TResult> SafeSelect<TSource, TResult>(
            IEnumerable<TSource> source,
            Func<TSource, TResult> selector)
        {
            if (source == null || selector == null)
            {
                return new List<TResult>();
            }
            
            try
            {
                return source.Select(selector).ToList();
            }
            catch (InvalidOperationException)
            {
                // ✅ If enumeration fails, work with a snapshot
                var snapshot = source.ToList();
                return snapshot.Select(selector).ToList();
            }
        }

        // ✅ Safe order by operation
        public static List<T> SafeOrderBy<T, TKey>(
            IEnumerable<T> source,
            Func<T, TKey> keySelector)
        {
            if (source == null || keySelector == null)
            {
                return new List<T>();
            }
            
            try
            {
                return source.OrderBy(keySelector).ToList();
            }
            catch (InvalidOperationException)
            {
                // ✅ If enumeration fails, work with a snapshot
                var snapshot = source.ToList();
                return snapshot.OrderBy(keySelector).ToList();
            }
        }

        // ✅ Safe distinct operation
        public static List<T> SafeDistinct<T>(IEnumerable<T> source)
        {
            if (source == null)
            {
                return new List<T>();
            }
            
            try
            {
                return source.Distinct().ToList();
            }
            catch (InvalidOperationException)
            {
                // ✅ If enumeration fails, work with a snapshot
                var snapshot = source.ToList();
                return snapshot.Distinct().ToList();
            }
        }

        // ✅ Safe group by operation
        public static Dictionary<TKey, List<TSource>> SafeGroupBy<TSource, TKey>(
            IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector)
        {
            if (source == null || keySelector == null)
            {
                return new Dictionary<TKey, List<TSource>>();
            }
            
            try
            {
                return source.GroupBy(keySelector).ToDictionary(g => g.Key, g => g.ToList());
            }
            catch (InvalidOperationException)
            {
                // ✅ If enumeration fails, work with a snapshot
                var snapshot = source.ToList();
                return snapshot.GroupBy(keySelector).ToDictionary(g => g.Key, g => g.ToList());
            }
        }
    }
}

Working Code Examples

Complete C# Application with Safe Operations:

// Program.cs
using MyCSharpApp.Services;
using MyCSharpApp.Utilities;
using MyCSharpApp.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

var builder = WebApplication.CreateBuilder(args);

// ✅ Add services to the container
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// ✅ Register custom services
builder.Services.AddScoped<ICollectionService, CollectionService>();
builder.Services.AddScoped<IStateService, StateService>();

var app = builder.Build();

// ✅ Demonstrate safe operations
try
{
    // ✅ Safe collection operations
    var collectionService = new CollectionService();
    var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
    Console.WriteLine("Original numbers: " + string.Join(", ", numbers));
    
    // ✅ Remove even numbers safely
    collectionService.RemoveEvenNumbers(numbers);
    Console.WriteLine("After removing even numbers: " + string.Join(", ", numbers));

    // ✅ Safe LINQ operations
    var emptyList = new List<int>();
    var firstElement = CollectionHelper.SafeFirstOrDefault(emptyList, -1);
    Console.WriteLine($"First element from empty list: {firstElement}");

    // ✅ Safe state service operations
    var stateService = new StateService();
    stateService.Initialize();
    stateService.ProcessData("Sample Data");
    Console.WriteLine($"Service data: {stateService.GetData()}");

    // ✅ Safe enumeration
    var items = new[] { "apple", "banana", "cherry" };
    var upperCaseItems = EnumeratorHelper.SafeSelect(items, s => s.ToUpper());
    Console.WriteLine($"Uppercase items: {string.Join(", ", upperCaseItems)}");

    // ✅ Safe collection processor
    using (var processor = new CollectionProcessor<string>())
    {
        processor.Add("item1");
        processor.Add("item2");
        processor.Add("item3");
        
        Console.WriteLine($"Processor count: {processor.Count}");
        
        var filteredItems = processor.FilterItems(s => s.Contains("item"));
        Console.WriteLine($"Filtered items: {string.Join(", ", filteredItems)}");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

// ✅ Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

Controller with Safe Operations:

// Controllers/DataController.cs
using Microsoft.AspNetCore.Mvc;
using MyCSharpApp.Services;
using MyCSharpApp.Utilities;
using MyCSharpApp.Models;
using System.Collections.Generic;
using System.Linq;

namespace MyCSharpApp.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class DataController : ControllerBase
    {
        private readonly ICollectionService _collectionService;
        private readonly IStateService _stateService;

        public DataController(ICollectionService collectionService, IStateService stateService)
        {
            _collectionService = collectionService;
            _stateService = stateService;
        }

        [HttpPost("process-numbers")]
        public IActionResult ProcessNumbers([FromBody] ProcessNumbersRequest request)
        {
            if (request?.Numbers == null)
            {
                return BadRequest("Numbers cannot be null");
            }

            try
            {
                // ✅ Safe collection processing
                var numbers = request.Numbers.ToList();
                _collectionService.RemoveEvenNumbers(numbers);
                
                return Ok(new { ProcessedNumbers = numbers, RemovedCount = request.Numbers.Count - numbers.Count });
            }
            catch (System.InvalidOperationException ex)
            {
                return BadRequest(new { Error = ex.Message });
            }
        }

        [HttpPost("filter-data")]
        public IActionResult FilterData([FromBody] FilterDataRequest request)
        {
            if (request?.Items == null)
            {
                return BadRequest("Items cannot be null");
            }

            try
            {
                // ✅ Safe filtering with helper methods
                var filteredItems = CollectionHelper.SafeWhere(request.Items, item => 
                    item.Contains(request.SearchTerm, System.StringComparison.OrdinalIgnoreCase));
                
                return Ok(new { FilteredItems = filteredItems, TotalCount = filteredItems.Count });
            }
            catch (System.InvalidOperationException ex)
            {
                return BadRequest(new { Error = ex.Message });
            }
        }

        [HttpGet("state-service-data")]
        public IActionResult GetStateServiceData()
        {
            try
            {
                // ✅ Safe state service usage
                if (!_stateService.IsInitialized)
                {
                    _stateService.Initialize();
                }
                
                var data = _stateService.GetData();
                return Ok(new { Data = data, IsInitialized = _stateService.IsInitialized });
            }
            catch (System.InvalidOperationException ex)
            {
                return BadRequest(new { Error = ex.Message });
            }
        }

        [HttpPost("add-state-data")]
        public IActionResult AddStateData([FromBody] AddStateDataRequest request)
        {
            if (string.IsNullOrEmpty(request?.Data))
            {
                return BadRequest("Data cannot be null or empty");
            }

            try
            {
                // ✅ Safe state service usage
                if (!_stateService.IsInitialized)
                {
                    _stateService.Initialize();
                }
                
                _stateService.ProcessData(request.Data);
                return Ok(new { Message = "Data added successfully", CurrentData = _stateService.GetData() });
            }
            catch (System.InvalidOperationException ex)
            {
                return BadRequest(new { Error = ex.Message });
            }
        }

        [HttpGet("safe-first")]
        public IActionResult GetFirstItem([FromQuery] List<string> items)
        {
            if (items == null || items.Count == 0)
            {
                return BadRequest("Items list cannot be null or empty");
            }

            try
            {
                // ✅ Safe First operation
                var firstItem = CollectionHelper.SafeFirst(items, "No items found");
                return Ok(new { FirstItem = firstItem });
            }
            catch (System.InvalidOperationException ex)
            {
                return BadRequest(new { Error = ex.Message });
            }
        }
    }

    public class ProcessNumbersRequest
    {
        public List<int> Numbers { get; set; } = new List<int>();
    }

    public class FilterDataRequest
    {
        public List<string> Items { get; set; } = new List<string>();
        public string SearchTerm { get; set; } = string.Empty;
    }

    public class AddStateDataRequest
    {
        public string Data { get; set; } = string.Empty;
    }
}

Unit Test Example:

// MyCSharpApp.Tests/UnitTests.cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyCSharpApp.Services;
using MyCSharpApp.Utilities;
using MyCSharpApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MyCSharpApp.Tests
{
    [TestClass]
    public class InvalidOperationExceptionTests
    {
        [TestMethod]
        public void CollectionService_RemoveEvenNumbers_DoesNotThrow()
        {
            // ✅ Arrange
            var service = new CollectionService();
            var numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
            
            // ✅ Act
            service.RemoveEvenNumbers(numbers);
            
            // ✅ Assert
            Assert.AreEqual(3, numbers.Count);
            Assert.IsTrue(numbers.Contains(1));
            Assert.IsTrue(numbers.Contains(3));
            Assert.IsTrue(numbers.Contains(5));
        }

        [TestMethod]
        public void CollectionHelper_SafeFirst_EmptyList_ReturnsDefault()
        {
            // ✅ Arrange
            var emptyList = new List<int>();
            
            // ✅ Act
            var result = CollectionHelper.SafeFirst(emptyList, -1);
            
            // ✅ Assert
            Assert.AreEqual(-1, result);
        }

        [TestMethod]
        public void CollectionHelper_SafeFirst_NonEmptyList_ReturnsFirst()
        {
            // ✅ Arrange
            var list = new List<int> { 10, 20, 30 };
            
            // ✅ Act
            var result = CollectionHelper.SafeFirst(list);
            
            // ✅ Assert
            Assert.AreEqual(10, result);
        }

        [TestMethod]
        public void StateService_InitializeThenDispose_CannotUseAfterDisposal()
        {
            // ✅ Arrange
            var service = new StateService();
            service.Initialize();
            service.Dispose();
            
            // ✅ Act & Assert
            Assert.ThrowsException<ObjectDisposedException>(() => 
                service.ProcessData("test"));
        }

        [TestMethod]
        public void CollectionProcessor_AddThenDispose_CannotUseAfterDisposal()
        {
            // ✅ Arrange
            var processor = new CollectionProcessor<string>();
            processor.Add("test");
            
            // ✅ Act
            processor.Dispose();
            
            // ✅ Assert
            Assert.ThrowsException<ObjectDisposedException>(() => 
                processor.Add("another"));
        }

        [TestMethod]
        public void EnumeratorHelper_SafeWhere_ModifiedDuringIteration_DoesNotThrow()
        {
            // ✅ Arrange
            var list = new List<int> { 1, 2, 3, 4, 5 };
            var result = new List<int>();
            
            // ✅ Act - this would normally throw if modifying during iteration
            // But our helper handles it safely
            var filtered = EnumeratorHelper.SafeWhere(list, x => x % 2 == 0);
            
            // ✅ Assert
            Assert.AreEqual(2, filtered.Count);
            Assert.IsTrue(filtered.Contains(2));
            Assert.IsTrue(filtered.Contains(4));
        }

        [TestMethod]
        public void CollectionService_ProcessCollectionWhileModifying_DoesNotThrow()
        {
            // ✅ Arrange
            var service = new CollectionService();
            var numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
            
            // ✅ Act
            service.ProcessCollectionWhileModifying(numbers);
            
            // ✅ Assert - all even numbers should be removed
            Assert.AreEqual(3, numbers.Count);
            Assert.IsFalse(numbers.Contains(2));
            Assert.IsFalse(numbers.Contains(4));
            Assert.IsFalse(numbers.Contains(6));
        }
    }
}

Best Practices for InvalidOperationException Prevention

1. Always Validate Object State

// ✅ Validate object state before operations
private void ValidateState()
{
    if (_disposed)
        throw new ObjectDisposedException(GetType().Name);
    
    if (!_initialized)
        throw new InvalidOperationException("Object is not initialized");
}

2. Use Safe LINQ Operations

// ✅ Use safe LINQ operations
var result = CollectionHelper.SafeFirstOrDefault(source, defaultValue);

3. Create Snapshots When Needed

// ✅ Create snapshots to avoid modification during iteration
var snapshot = source.ToList();
foreach (var item in snapshot)
{
    // Safe to modify original collection
}

4. Implement Proper Dispose Pattern

// ✅ Implement proper dispose pattern
public void Dispose()
{
    if (!_disposed)
    {
        // Cleanup resources
        _disposed = true;
    }
}

5. Use Locks for Thread Safety

// ✅ Use locks for thread-safe operations
private readonly object _lock = new object();
lock (_lock)
{
    // Thread-safe operations
}

6. Validate Parameters

// ✅ Validate method parameters
public void ProcessData(List<int> data)
{
    if (data == null)
        throw new ArgumentNullException(nameof(data));
    
    // Continue with processing
}

Debugging Steps

Step 1: Identify the Problematic Operation

# Look for the stack trace to identify where the exception occurs
# The stack trace will show the exact line number and operation

Step 2: Check Collection Modification During Iteration

// Verify that collections are not being modified during iteration
foreach (var item in collection)
{
    // ❌ Don't modify collection here
    // collection.Remove(item); // This would cause InvalidOperationException
}

Step 3: Check Object State

// Verify that objects are in the correct state
if (object.IsDisposed)
{
    throw new ObjectDisposedException("Object has been disposed");
}

Step 4: Use Debugging Tools

# Use Visual Studio debugger to inspect object states
# Set breakpoints and examine collection states and object lifetimes

Step 5: Review LINQ Operations

// Check LINQ operations for empty sequences
var result = source.FirstOrDefault(); // ✅ Safe
var result = source.First(); // ❌ Can throw if empty

Common Mistakes to Avoid

1. Modifying Collections During Iteration

// ❌ Modifying collection during foreach
foreach (var item in list)
{
    if (condition)
        list.Remove(item); // ❌ InvalidOperationException
}

2. Using Disposed Objects

// ❌ Using object after disposal
var stream = new FileStream("file.txt", FileMode.Open);
stream.Dispose();
stream.Read(buffer, 0, buffer.Length); // ❌ InvalidOperationException

3. Calling Methods in Wrong State

// ❌ Calling method when object is not ready
var reader = new StreamReader(stream);
reader.Close(); // Stream is now closed
var content = reader.ReadToEnd(); // ❌ InvalidOperationException

4. Using LINQ on Empty Sequences

// ❌ Using First() on empty sequence
var emptyList = new List<int>();
var first = emptyList.First(); // ❌ InvalidOperationException

5. Incorrect Enumerator Usage

// ❌ Incorrect enumerator usage
var enumerator = collection.GetEnumerator();
var first = enumerator.Current; // ❌ InvalidOperationException - not moved yet

Performance Considerations

1. Minimize Collection Copies

// ❌ Creating unnecessary copies
var copy = source.ToList(); // If not needed
foreach (var item in copy) { /* process */ }

2. Use Appropriate Data Structures

// ✅ Use appropriate data structures for the operation
// For frequent additions/removals, consider LinkedList
// For lookups, consider HashSet or Dictionary

3. Optimize LINQ Operations

// ✅ Optimize LINQ operations
var result = source.Where(condition).ToList(); // Better than multiple operations

Security Considerations

1. Validate Input Before Processing

// ✅ Validate input to prevent invalid operations
public void ProcessData(List<string> data)
{
    if (data == null)
        throw new ArgumentNullException(nameof(data));
    
    if (data.Count > MAX_ALLOWED_SIZE)
        throw new ArgumentException("Data size exceeds limit");
    
    // Safe to process
}

2. Handle State Changes Securely

// ✅ Secure state management
private void ChangeState(SecurityLevel level)
{
    if (_securityLevel < level)
        throw new InvalidOperationException("Insufficient security level");
    
    _securityLevel = level;
}

3. Protect Against Race Conditions

// ✅ Thread-safe operations
private readonly object _lock = new object();
public void SafeOperation()
{
    lock (_lock)
    {
        // Thread-safe code
    }
}

Testing InvalidOperationException Scenarios

1. Test Collection Modification

[TestMethod]
public void RemoveItemsDuringIteration_DoesNotThrow()
{
    var service = new CollectionService();
    var list = new List<int> { 1, 2, 3, 4, 5 };
    
    // This should not throw InvalidOperationException
    service.RemoveEvenNumbers(list);
    
    Assert.AreEqual(3, list.Count);
}

2. Test Disposed Object Usage

[TestMethod]
public void UseAfterDisposal_ThrowsObjectDisposedException()
{
    var service = new StateService();
    service.Dispose();
    
    Assert.ThrowsException<ObjectDisposedException>(() => 
        service.ProcessData("test"));
}

3. Test LINQ Operations on Empty Collections

[TestMethod]
public void LinqOperationsOnEmptyCollection_DoNotThrow()
{
    var emptyList = new List<int>();
    
    // These should not throw
    var first = CollectionHelper.SafeFirstOrDefault(emptyList);
    var count = CollectionHelper.SafeCount(emptyList);
    
    Assert.AreEqual(0, first);
    Assert.AreEqual(0, count);
}

Alternative Solutions

1. Use Immutable Collections

// ✅ Use immutable collections to prevent modification during iteration
using System.Collections.Immutable;
var immutableList = ImmutableList.Create(1, 2, 3, 4, 5);

2. Use Concurrent Collections

// ✅ Use concurrent collections for thread-safe operations
using System.Collections.Concurrent;
var concurrentList = new ConcurrentBag<int>();

3. Use ReadOnly Collections

// ✅ Use read-only collections when modification is not needed
var readOnlyList = new List<int> { 1, 2, 3 }.AsReadOnly();

Migration Checklist

  • Review all foreach loops for collection modifications
  • Replace unsafe LINQ operations with safe helpers
  • Implement proper dispose patterns
  • Add state validation to all methods
  • Update unit tests to cover InvalidOperationException scenarios
  • Test all collection operations for thread safety
  • Verify object lifecycle management
  • Test disposed object usage scenarios

Conclusion

The ‘InvalidOperationException’ is a common but preventable C# runtime issue that occurs when operations are performed on objects in invalid states. By following the solutions provided in this guide—implementing proper collection handling, using safe LINQ operations, managing object states correctly, and following best practices—you can effectively prevent and resolve this error in your C# applications.

The key is to understand the conditions under which operations are valid, implement defensive programming practices, use modern C# features for safe operations, and maintain clean, well-organized code. With proper state management and collection handling, your C# applications will be more resilient and less prone to runtime exceptions.

Remember to test your changes thoroughly, follow C# best practices for state management, implement proper error handling, and regularly review your code for potential state-related issues to ensure your applications maintain the best possible architecture and avoid common runtime errors like InvalidOperationException.

Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

csharp

Fix: Index was outside the bounds of the array C# error

Learn how to fix the 'Index was outside the bounds of the array' error in C# applications. This comprehensive guide covers array indexing, bounds checking, and proper collection access techniques.

January 8, 2026
csharp

Fix: CS0246: The type or namespace name could not be found error

Learn how to fix the 'CS0246: The type or namespace name could not be found' error in C# applications. This comprehensive guide covers using statements, assembly references, and proper namespace management.

January 8, 2026
csharp

Fix: CS0103: The name does not exist in the current context error

Learn how to fix the 'CS0103: The name does not exist in the current context' error in C# applications. This comprehensive guide covers variable scope, method accessibility, and proper context management.

January 8, 2026