views:

130

answers:

6

I have a Dictionary that when I add multiple values to it, the items that were entered before take the values of the item added. I am using the .Net 3.5 Here is the code:

public static Dictionary<string, Neighborhoods> Families()
    {
        if (File.Exists(calculatePath() + "Family.txt")){}
        else {File.Create(calculatePath() + "Family.txt").Close();}
        string[] inp = File.ReadAllLines(calculatePath() + "Family.txt");
        Neighborhoods temp = new Neighborhoods();
        Dictionary<string, Neighborhoods> All_Families = new Dictionary<string, Neighborhoods>();
        string currentphase = null;
        foreach (string s in inp)
        {
            switch (s)
            {
                case "!<Start Family>!": temp = new Neighborhoods();
                    break;
                case "<Family Name>": currentphase = "<Family Name>";
                    break;
                case "<End Family Name>": currentphase = null;
                    break;
                case "<Neighbour Enabled>True": temp.Neighbourhood_Enabled1 = true;
                    currentphase = "<Neighbour Enabled>True";
                    break;
                case "<Neighbour Enabled>False": temp.Neighbourhood_Enabled1 = false;
                    temp.Neighbourhood_Input1 = null;
                    break;
                case "<University Enabled>True": temp.University_Enabled1 = true;
                    currentphase = "<University Enabled>True";
                    break;
                case "<University Enabled>False": temp.University_Enabled1 = false;
                    temp.University_Input1 = null;
                    currentphase = null;
                    break;
                case "<Downtown Enabled>True": temp.Downtown_Enabled1 = true;
                    currentphase = "<Downtown Enabled>True";
                    break;
                case "<Downtown Enabled>False": temp.Downtown_Enabled1 = false;
                    temp.Downtown_Input1 = null;
                    currentphase = null;
                    break;
                case "!<End Family>!": All_Families.Add(temp.Name, temp);
                    break;
                default: if (currentphase == "<Family Name>") temp.Name = s;
                    if (currentphase == "<Neighbour Enabled>True") temp.Neighbourhood_Input1 = s;
                    if (currentphase == "<University Enabled>True") temp.University_Input1 = s;
                    if (currentphase == "<Downtown Enabled>True") temp.Downtown_Input1 = s;
                    break;
            }
        }
        return All_Families;
    }

How can I make it so that when I add new keys and values, the old keys keep their original value

A: 

No, they don't have duplicate keys. It is just that the values in the dictionary are overwritten by the last value entered.

Jonathan Camilleri
Your parser is insane. What is wrong with using XML in this situation?
FlySwat
Jonathan Camilleri: Okay, then I'm confused. I'm not really sure what you're asking or what you're saying in this answer. Can you clarify the question so we can try to help you?
Blair Conrad
That would only happen if either you didn't get a "!<Start Family>!" line, or you had duplicate keys.
Jon Skeet
when i ran the whole thing in debugger, when the first family was read all was fine, but when the second family was added with all the values correct and different the first family's values were overwritten by the second one's
Jonathan Camilleri
@Jonathan: Then I strongly suspect you're not going through the "!<Start Family>!" line - so it's still using the same object as before. However, we won't know without seeing a sample data file.
Jon Skeet
The problem is different but I will add some sample data
Jonathan Camilleri
+2  A: 

From the looks of it, you want to parse a file, and load it into a Dictionary collection.

A couple critiques...Use XML for one, and get rid of the insane parser:

<?xml version="1.0" encoding="utf-8"?>
<families>
  <family>
    <name>Smith</name>
    <neighborhood>true</neighborhood>
    <university>false</university>
    <downtown>false</downtown>
  </family>
  <family>
    <name>Jones</name>
    <neighborhood>false</neighborhood>
    <university>true</university>
    <downtown>false</downtown>
  </family>
</families>

Now, we can use the built in System.XML namespace to parse this far easier.

For example, I just rewrote your code as:

        Dictionary<String, Neighborhood> families = new Dictionary<string, Neighborhood>();

        XmlDocument doc = new XmlDocument();
        doc.Load("family.xml");

        foreach (XmlNode familyNode in doc.SelectNodes("//family"))
        {
            Neighborhood n = new Neighborhood();
            n.Name = familyNode.SelectSingleNode("name").InnerText;
            n.InNeighborhood = Boolean.Parse(familyNode.SelectSingleNode("neighborhood").InnerText);
            n.InDowntown = Boolean.Parse(familyNode.SelectSingleNode("downtown").InnerText);
            n.InUniversity = Boolean.Parse(familyNode.SelectSingleNode("university").InnerText);

            families.Add(n.Name,n);
        }

And it works just fine, though I didn't add any error handling to my code to keep it brief.

FlySwat
I think this is the answer. Jonathan, if you're right about the purpose (and I think you are), the problem was that there was one Neighborhood object created. Its members were overwritten multiple times, but the same object was stored in the Dictionary over and over, so all values were identical.
Blair Conrad
The problem with his parser is that if you didn't have a "Start Family" immediatly after a "end Family", it would break.
FlySwat
A: 

Sample data:

!<Start Family>!
Family Name>
qwe
<End Family Name>
<Neighbour Enabled>True
qwe
<University Enabled>True
we
<Downtown Enabled>True
qwe
!<End Family>!
!<Start Family>!
<Family Name>
123
<End Family Name>
<Neighbour Enabled>True
123
<University Enabled>True
123
<Downtown Enabled>True
123
!<End Family>!
Jonathan Camilleri
Out of curiosity, did you event this format yourself? Or are you forced to work with it as its from another product?
FlySwat
event should be invent.
FlySwat
+2  A: 

With the sample data you've given and the code you've given, it works okay using a Neighborhoods class like this:

public class Neighborhoods
{
    public string Name { get; set; }
    public string Neighbourhood_Input1 { get; set; }
    public string University_Input1 { get; set; }
    public string Downtown_Input1 { get; set; }
    public bool Neighbourhood_Enabled1 { get; set; }
    public bool University_Enabled1 { get; set; }
    public bool Downtown_Enabled1 { get; set; }
}

My test is to run this code:

static void Main()
{
    var families = Families();

    foreach (var family in x.Values)
    {
        Console.WriteLine(y.Name);
    }
}

That prints out "qwe" and "123" - showing that there are two different objects involved.

However, we haven't seen the real Neighborhoods class yet. I don't suppose it's using static fields (but still instance properties) is it? That would certainly explain the behaviour you're seeing.

EDIT: Yup, now you've shown us the Neighborhoods code it makes sense. Those fields are meant to be relevant for each instance, not just the type itself - so they shouldn't be static.

To show this is nothing to do with the parser, try this:

Neighborhoods first = new Neighborhoods();
Neighborhoods second = new Neighborhoods();

first.Name = "First";
Console.WriteLine(second.Name);

You'll see it prints out "First" - which is clearly not what you want!

Unfortunately I don't have a good page about what "static" means, but I suggest you look it up in whatever C# books you have.

Jon Skeet
Declaring the fields as static was the problem. 10ks for helping.
Jonathan Camilleri
A: 

Here is the nieghbourhoods class for reference. I will try the xml methods but it wont be finished quickly, I'm still learning this stuff.

class Neighborhoods
{
    public Neighborhoods()
    {
        name = "";
        Neighbourhood_Enabled = false;
        Neighbourhood_Input = "";
        University_Enabled = false;
        University_Input = "";
        Downtown_Enabled = false;
        Downtown_Input = "";
    }

    static string name;

    public string Name
    {
        get { return Neighborhoods.name; }
        set { Neighborhoods.name = value; }
    }
    static bool Neighbourhood_Enabled;

    public bool Neighbourhood_Enabled1
    {
        get { return Neighborhoods.Neighbourhood_Enabled; }
        set { Neighborhoods.Neighbourhood_Enabled = value; }
    }
    static string Neighbourhood_Input;

    public string Neighbourhood_Input1
    {
        get { return Neighborhoods.Neighbourhood_Input; }
        set { Neighborhoods.Neighbourhood_Input = value; }
    }
    static bool University_Enabled;

    public bool University_Enabled1
    {
        get { return Neighborhoods.University_Enabled; }
        set { Neighborhoods.University_Enabled = value; }
    }
    static string University_Input;

    public string University_Input1
    {
        get { return Neighborhoods.University_Input; }
        set { Neighborhoods.University_Input = value; }
    }
    static bool Downtown_Enabled;

    public bool Downtown_Enabled1
    {
        get { return Neighborhoods.Downtown_Enabled; }
        set { Neighborhoods.Downtown_Enabled = value; }
    }
    static string Downtown_Input;

    public string Downtown_Input1
    {
        get { return Neighborhoods.Downtown_Input; }
        set { Neighborhoods.Downtown_Input = value; }
    }
}
Jonathan Camilleri
A: 

Like Jon Skeet noted, you can't use static like that.

replace static with private and all should be well.

FlySwat