views:

157

answers:

3

I want to have an ArrayList where it contains HashTables. I create a Hashtable and added values. I then added it to the ArrayList. I then changed the values of the Hashtables and added it again the Array List. It does not save the first values and ending having duplicated values which were exactly the same as the last values!

Any suggestions? Here is my code

namespace ValuesTest
{
    internal class Class1
    {    
        public static ArrayList StartList = new ArrayList();
        public static Hashtable Start = new Hashtable();    

        static void Main(string[] args)
        {    
            Start["active"] = true;
            Start["name"] = "prog1";
            Start["path"] = @"C:\programfiles\prog1";
            Start["parameter"] = string.Empty;

            StartList.Add(Start);

            Start["active"] = false;
            Start["name"] = "prog2";
            Start["path"] = @"C:\programfiles\prog2";
            Start["parameter"] = "/q";

            StartList.Add(Start);

            foreach (Hashtable HT in StartList)
            {
                Console.WriteLine(HT["active"] + " - " + HT["name"] + " - " + HT["path"] + " - " + HT["parameter"]);
                // it will always gives
                // False - prog2 - C:\programfiles\prog2 - /q    
            }

            Console.ReadLine();   
        }
    }
}
+6  A: 

You're modifying the one and only Start Hashtable object, you must create a new one:

Start = new Hashtable();

right after the first:

StartList.Add(Start);

Remember, you're only adding a reference to the object to the ArrayList: so what your code does is: populate a hashtable, add a reference to it to the list, modify it some more, and add the same reference again.


Would like to add, why are you using a hashtable? It would be far better to use a new class with the fields you desire - then they could have a PrintInfo, or a ToString override that gets the information you need - and presumably an Execute method.

Kieren Johnstone
I'm not sure, this is the way I know so I can serialize it later :-)do you have an example similar to mine? that make me able to serialize it?
Data-Base
Yes, depending on how and why you are serialising, you just mark the class with `[Serializable]` at the top. See example here: http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx and guide here: http://msdn.microsoft.com/en-us/library/ms973893.aspx .
Kieren Johnstone
+5  A: 

Move start to inside your Main function, and reinitialize it for the second add(and as @lasseespeholt said use List<T>).

    static List<Hashtable> StartList = new List<Hashtable>();

    static void Main(string[] args)
    {
        Hashtable Start = new Hashtable();
        Start["active"] = true;
        Start["name"] = "prog1";
        Start["path"] = @"C:\programfiles\prog1";
        Start["parameter"] = string.Empty;

        StartList.Add(Start);

        Start = new Hashtable();
        Start["active"] = false;
        Start["name"] = "prog2";
        Start["path"] = @"C:\programfiles\prog2";
        Start["parameter"] = "/q";

        StartList.Add(Start);
Nix
Thanks allot :-)
Data-Base
+1  A: 

Some more feedback on this: Although Nix already answered your question, I'd drop Hashtable as well (just as ArrayList it's dated), although your concept doesn't lend itself nice to it: You store string to object..

So, copying and changing we'd end up with

 static void Main(string[] args)
 {
        Dictionary<string, object> Start = new Dictionary<string, object>();
        Start["active"] = true;
        Start["name"] = "prog1";
        Start["path"] = @"C:\programfiles\prog1";
        Start["parameter"] = string.Empty;

        StartList.Add(Start);

        Dictionary<string, object> Start = new Dictionary<string, object>();
        Start["active"] = false;
        Start["name"] = "prog2";
        Start["path"] = @"C:\programfiles\prog2";
        Start["parameter"] = "/q";

        StartList.Add(Start);

But I'd go further: If you just want to spawn processes, that's what the class Process is for. It keeps just the same information (except for "active") in the StartInfo property.

Another, (better?) approach would be to create a value class for this set of information:

class YourStartInfo
{
  public bool Active { get; set; }
  public string Name { get; set; }
  public string Path { get; set; }
  public string Parameter { get; set; }
}

and changing your code to make use of that:

 static List<YourStartInfo> StartList = new List<YourStartInfo>();

 static void Main(string[] args)
 {    
        StartList.Add(new YourStartInfo {
            Active = true,
            Name = "prog1",
            Path = @"C:\programfiles\prog1";
            Parameter = string.Empty
        });

        StartList.Add(new YourStartInfo {
            Active = false,
            Name = "prog2",
            Path = @"C:\programfiles\prog2";
            Parameter = "/q"
        });

        foreach (YourStartInfo startInfo in StartList)
        {
            // Access the information in a sane way, not as object here
            if (startInfo.Active)
            {
                 // Probably launch it?
            }
        }

        Console.ReadLine();   
    }
Benjamin Podszun
Actually that what I found my self doing now :-)but thanks for the suggestion :-)it give me a good push that I'm on the right path,cheers.
Data-Base