Home > Software design >  Is my foreach not iterating over all elements?
Is my foreach not iterating over all elements?

Time:12-01

So I have this piece of code, but it's not working as expected. You can copy and paste it and try it yourself.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Helper
{
    public static class Program
    {
        public static bool active = false;
        public static WorldData wdataTest = new WorldData(); // Simple test objects
        public static Dictionary<string, WorldData> dic = new Dictionary<string, WorldData>();
        public static void Main()
        {
            active = true;
            Start();
        }

        public static void Start()
        {
            dic.Add("test", wdataTest);
            System.Timers.Timer timer = new System.Timers.Timer();
            string serialized;
            bool loaded = false;
            int i = -10;
            int normalizedRate = 2;
            timer.Interval = 100;
            timer.AutoReset = true;
            timer.Elapsed  = new System.Timers.ElapsedEventHandler((_, __) => {
                try
                {
                    Stopwatch st = new Stopwatch();
                    st.Start();
                    if (active)
                    {
                        if (loaded)
                        {
                            i  ;
                        }
                        foreach (WorldData wData in dic.Values)
                        {
                            loaded = true;
                            foreach (EntityList collection in wData.collectionOfCollections)
                            {
                                serialized = JsonConvert.SerializeObject(collection.Entities);
                                // Does some other things
                                if (i == normalizedRate)
                                {
                                    WriteSerialized(collection, serialized);
                                    i = 0;
                                }
                            }
                        }
                    }
                    st.Stop();
                    Console.WriteLine(st.ElapsedMilliseconds.ToString());
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            });
            timer.Enabled = true;
            Console.ReadKey();
        }

        public static void WriteSerialized(EntityList collection, string serializedObj)
        {
            Console.WriteLine(collection.Name);
            // Write to file serializedObj
        }

        public class WorldData
        {
            public List<EntityList> collectionOfCollections;

            public WorldData()
            {
                collectionOfCollections = new List<EntityList>();
                collectionOfCollections.Add(new EntityList("hammers"));
                collectionOfCollections.Add(new EntityList("screwdrivers"));
                collectionOfCollections.Add(new EntityList("nails"));
                collectionOfCollections.Add(new EntityList("pcs"));
            }
        }

        public class EntityList
        {
            public List<object> Entities;
            public string Name { get; set; }
            public EntityList(string name)
            {
                Name = name;
                Entities = new List<object>();
                Entities.Add(new object());
            }
        }
    }
}

The code purpose is to serialize all those objects every 100ms to send to another program, and every 200ms write the serialized object to file for replay purposes (I have another piece of code that reads the files again later). I found out the bug after only a file had something written on it, so I used the Console.WriteLine to make sure it iterated over every collection. What I got is only "hammers" and 0 printed. I can believe it takes less than 1ms to complete the event in this example, but in my real application it has to serialize big objects and I have the same results. Hammers and 0. I put a breakpoint to debug it and checked that the collections are properly filled...what am I getting wrong?

EDIT: As per request I explained the purposes of the program in deeper details.

CodePudding user response:

i is increased at every call of the ElapsedEventHandler

if (active) // active is true
{
    if (loaded) // loaded is true
    {
        i  ;
    }
...

You print a collection name only when i is 2, then you immediately reset i to 0:

if (i == normalizedRate) // normalizedRate value is 2
{
    WriteSerialized(collection, serialized);
    i = 0;
}

Hence you get only the first collection name (hammers) as output every two calls of the handlers.

Because you also write the ElapsedMilliseconds at the end of the call:

Console.WriteLine(st.ElapsedMilliseconds.ToString());

The final result is hammers 0 0 hammers 0 0 ...

If the purpose of i is to do the output only once in a while (normalizedRate), you should reset it later, before st.Stop() maybe:

if (i == normalizedRate)
    i = 0;

st.Stop();
Console.WriteLine(st.ElapsedMilliseconds.ToString());
  • Related