Home > Blockchain >  System.InvalidOperationException: 'Collection was modified; enumeration operation may not execu
System.InvalidOperationException: 'Collection was modified; enumeration operation may not execu

Time:06-17

I'm trying to implement https://docs.microsoft.com/en-us/dotnet/standard/events/observer-design-pattern into my pet shop for a school project. However I keep running into this error. I already tried looking it up but most common solutions like .ToList(); or ToArray(); dont work.

My observer class:

namespace Weekopdracht_College1
{
    class ObservableStore : IObservable<Animal>
    {
        private List<IObserver<Animal>> observers;
        private List<Animal> animals; 

        public ObservableStore()
        {
            observers = new List<IObserver<Animal>>();
            animals = new List<Animal>();
        }

        public IDisposable Subscribe(IObserver<Animal> observer)
        {
            if (! observers.Contains(observer))
            {
                observers.Add(observer); 

                foreach(var item in animals)
                {
                    observer.OnNext(item); 
                }
            }
            return new Unsubscriber<Animal>(observers, observer); 
        }

        public void AddAnimal(int id)
        {
            AddAnimal(id, String.Empty, 0, 0); 
        }
        
        public void AddAnimal(int id, string type, double price, int stock)
        {
            var info = new Animal(id, type, price, stock);

            if (stock > 0 && ! animals.Contains(info))
            {
                animals.Add(info); 
                foreach (var observer in observers)
                {
                    observer.OnNext(info); 
                }
            }
            else if (stock == 0)
            {
                var animalsToRemove = new List<Animal>(); 
                foreach(var animal in animals) 
                {
                  if(info.AnimalId == animal.AnimalId)
                  {
                    animalsToRemove.Add(animal); 
                    foreach (var observer in observers)
                    {
                        observer.OnNext(info); 
                    }
                  }
                  foreach (var animalToRemove in animalsToRemove)
                  {
                      animals.Remove(animalToRemove);
                  
                       
                  }
                  animalsToRemove.Clear();
                }
            }
        }

        public void LastAnimalBought()
        {
            foreach (var observer in observers)
            {
                observer.OnCompleted(); 
            }
            observers.Clear(); 
        }

    }


}

This part doens't work:

else if (stock == 0)
            {
                var animalsToRemove = new List<Animal>(); 
                foreach(var animal in animals) <--- Error point
                {
                  if(info.AnimalId == animal.AnimalId)
                  {
                    animalsToRemove.Add(animal); 
                    foreach (var observer in observers)
                    {
                        observer.OnNext(info); 
                    }
                  }
                  foreach (var animalToRemove in animalsToRemove)
                  {
                      animals.Remove(animalToRemove);
                  
                       
                  }
                  animalsToRemove.Clear();
                }
            }

Animal class:

public class Animal
    {
        private int id { get; set; }
        private string type { get; set; }
        private double price { get; set; }
        private int stock { get; set; }

        internal Animal(int id, string type, double price, int stock)
        {
            this.id = id; 
            this.type = type;
            this.stock = stock;
            this.price = price; 
        }

        public int AnimalId
        {
            get { return this.id;  }
        }

        public string AnimalType {
            get { return this.type; }
        }

        public double AnimalStock
        {
            get { return this.stock; }
        }

        public double AnimalPrice { 
            get { return this.price; }
        }
    }

Display class:

namespace Weekopdracht_College1
{
    class StockScreen : IObserver<Animal>
    {
        private string name;
        private List<string> animalInfos = new List<string>();
        private IDisposable cancellation;
        private string fmt = "{0,-20} {1,5} {2, 3} {3,4}"; 

        public StockScreen(string name)
        {
            if (String.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("The observer must be assigned a name."); 

            }

            this.name = name; 
        }

        public virtual void Subscribe(ObservableStore provider)
        {
            cancellation = provider.Subscribe(this); 
        }

        public virtual void Unsubscribe()
        {
            cancellation.Dispose();
            animalInfos.Clear(); 
        }

        public virtual void OnCompleted()
        {
            animalInfos.Clear();
        }

        public virtual void one rror(Exception e)
        {
            // no implementation
        }

        public virtual void OnNext(Animal info)
        {
            bool updated = false; 

            if (info.AnimalStock == 0)
            {
                var animalsToRemove = new List<string>();
                string name = String.Format("{0,5}", info.AnimalId); 

                foreach(var animalInfo in animalInfos)
                {
                    if (animalInfo.Substring(21, 5).Equals(name))
                    {
                        animalsToRemove.Add(animalInfo); 
                    }

                    animalsToRemove.Clear(); 
                }
            }
            else
            {
                string animalInfo = String.Format(fmt, info.AnimalId, info.AnimalType, info.AnimalPrice, info.AnimalStock); 
                if (! animalInfos.Contains(animalInfo))
                {
                    animalInfos.Add(animalInfo);
                    updated = true; 
                }
            }

            if(updated)
            {
                animalInfos.Sort();
                Console.WriteLine("Animal information from: {0}", this.name); 
                foreach (var animalInfo in animalInfos)
                {
                    Console.WriteLine(animalInfo); 
                }

                Console.WriteLine(); 
            }
        }
    }
}

CodePudding user response:

Move the loop over animalsToRemove outside the foreach loop over animals:

var animalsToRemove = new List<Animal>(); 
foreach(var animal in animals) <--- Error point
{
    if(info.AnimalId == animal.AnimalId)
    {
         animalsToRemove.Add(animal); 
         foreach (var observer in observers)
         {
              observer.OnNext(info); 
         }
     }         
}

foreach (var animalToRemove in animalsToRemove)
{
    animals.Remove(animalToRemove);
}
animalsToRemove.Clear();
  • Related