2010-08-05 15 views
2

Je souhaite avoir une ArrayList contenant des Hashtables. Je crée une Hashtable et des valeurs ajoutées. Je l'ai ensuite ajouté à ArrayList. J'ai ensuite changé les valeurs des Hashtables et je l'ai ajouté de nouveau à la liste des tableaux. Il ne sauvegarde pas les premières valeurs et finit par avoir des valeurs dupliquées exactement identiques aux dernières valeurs!ArrayList de tables de hachage en C#

Des suggestions? Voici mon 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(); 
     } 
    } 
} 
+5

J'ai vu beaucoup de ArrayList récemment. Au lieu de cela, vous devez utiliser la liste sauf si vous utilisez .Net framework 1/1.1. La liste donnera de meilleures performances et évitera de lancer (ce que 'foreach' implicite dans votre cas). salutations –

+1

Vous ne créez pas une nouvelle instance de Hashtable, mais remplacez les valeurs. P.S.: L'utilisation de plusieurs points d'exclamation dans le sujet n'est pas très utile si vous attendez une réponse: p –

+0

Cependant, les gens devraient voter sur la question, pas sur la grammaire. –

Répondre

8

Déplacez le début à l'intérieur de votre fonction principale, et réinitialisez-le pour le second ajout (et comme @lasseespeholt dit utiliser 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); 
6

vous modifiez la seul et uniqueStart objet Hashtable, vous devez créer une nouvelle:

Start = new Hashtable();

juste après la première:

StartList.Add(Start);

Rappelez-vous, vous n'ajoutez qu'une référence à l'objet à l'ArrayList: donc ce que fait votre code: remplir une hashtable, ajouter une référence à la liste, le modifier un peu plus, et ajouter la même référence encore.


Aimeriez-vous ajouter, pourquoi utilisez-vous une table de hachage? Il serait préférable d'utiliser une nouvelle classe avec les champs que vous désirez - alors ils pourraient avoir un PrintInfo, ou un ToString override qui obtient l'information dont vous avez besoin - et probablement une méthode Execute.

+1

Je ne suis pas sûr, c'est la façon dont je sais que je peux le sérialiser plus tard :-) avez-vous un exemple semblable au mien? qui me rends capable de le sérialiser? –

+0

Oui, en fonction du mode et de la raison de la sérialisation, il vous suffit de marquer la classe avec '[Serializable]' en haut. Voir l'exemple ici: http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx et guide ici: http://msdn.microsoft.com/en-us/library/ms973893.aspx. –

1

Certains plus de commentaires à ce sujet: Bien que Nix déjà répondu à votre question, je laisse tomber Hashtable aussi bien (comme ArrayList il est daté), bien que votre concept ne se prête pas bien à elle: Vous stockez chaîne à l'objet ..

Ainsi, la copie et le changement que nous finirions avec

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); 

Mais j'aller plus loin: Si vous voulez juste reproduire les processus, c'est ce que la classe Process est pour. Il garde juste la même information (sauf pour "actif") dans la propriété StartInfo.

Une autre, (? Mieux) approche serait de créer une classe de valeur pour cet ensemble d'informations:

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

et changer votre code pour utiliser que:

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(); 
    } 
+0

En fait que ce que j'ai trouvé mon self faire maintenant :-) mais merci pour la suggestion :-) il me donner une bonne poussée que je suis sur le bon chemin, acclamations. –