I was wondering if you could look at my code and see where I have gone wrong. Basically, I have created an object of type “UserFile”(my own object type) and am creating 2 instances of it and within the constructor of that object, I am calling a static class method. All goes well for them except the second instance overwrites the first one after the object constructor is called. I have stepped through the program and am thoroughly confused. I get the feeling im missing something very obvious here.
Here is the button on the form that creates the instances
private void btnCompare_Click(object sender, EventArgs e)
{
if (lstFiles.CheckedItems.Count == 2)
{
file1 = new UserFile(((FileLocation)lstFiles.CheckedItems[0]).filePath);
file2 = new UserFile(((FileLocation)lstFiles.CheckedItems[1]).filePath);
}
}
Here is the UserFile class with constructor
public class UserFile
{
public Dictionary<int,Individual> fileIndividuals;
public Dictionary<int, Family> fileFamilies;
public Header fileHead;
public UserFile(string _dir)
{
fileIndividuals = new Dictionary<int, Individual>();
fileFamilies = new Dictionary<int, Family>();
fileHead = new Header();
ReadFromFile.Read(_dir);
fileIndividuals = ReadFromFile.individuals;
fileFamilies = ReadFromFile.families;
fileHead = ReadFromFile.head;
}
}
Here is the ReadFromFile method called by the UserFile class
static class ReadFromFile
{
public static string filename = "";
public static Header head;
public static Individual individual;
public static Dictionary<int, Individual> individuals = new Dictionary<int, Individual>();
public static Family family;
public static Dictionary<int, Family> families = new Dictionary<int, Family>();
public static GedcomRecordEnum currentRecord = GedcomRecordEnum.None;
public static GedcomSubRecordEnum currentFirstLvlRecord = GedcomSubRecordEnum.None;
public static GedcomSecondLevelEnum currentSecondLvlRecord = GedcomSecondLevelEnum.None;
static public void Read(string fileName)
{
individuals.Clear();
families.Clear();
head = null;
if (File.Exists(fileName))
{
filename = fileName;
StreamReader reader = new StreamReader(fileName);
while (!reader.EndOfStream)
{
string currentLine = reader.ReadLine();
Match m = Regex.Match(currentLine, "(?<index>[0-9]) (?<keyword>[A-Z_@0-9]+)(?: *)(?<detail>.*)");
string debug = m.Groups["index"].ToString();
switch (m.Groups["index"].ToString())
{
case "0":
ProcessRootLevel(m.Groups["keyword"].ToString());
break;
case "1":
ProcessLevel1(m.Groups["keyword"].ToString(), m.Groups["detail"].ToString());
break;
case "2":
ProcessLevel2(m.Groups["keyword"].ToString(), m.Groups["detail"].ToString());
break;
case "3":
ProcessLevel3(m.Groups["keyword"].ToString(), m.Groups["detail"].ToString());
break;
}
}
reader.Close();
}
}
}
The problem is the following static properties on the
ReadFromFileclass, if I assume by “overwritten” you mean that both instances ofUserFilepoint to the same data:The problem lies in the constructor of
UserFileon the use of static properties.What happens here is the member variables
fileIndividuals,fileFamiliesandfileHeadare set to a reference of theindividuals,familiesandheadproperties on the staticReadFromFileclass, not a copy (as they are classes and not value types). So the next timeReadFromFile.Read()is called the static properties onReadFromFileare updated (overwritten), but the prior instance ofUserFilejust points to the same static properties, ergofile1andfile2will have the same data.So how would you fix this? Two options:
ReadFromFileand instance class, and not a static one. Construct a new instance in theUserFileconstructor and don’t use any static properties.individuals,familiesandheadin the constructor ofUserFile. “foreach” through each item, and copy it into a new dictionary.Simple explanation:
When you do an assign (the = character in C#) if the object is a class, then the target is assigned a “pointer” (reference) to the right hand side. If it’s a value type it’s copied. Dictionary is a class, so you get a pointer and not a copy.
Illustration in code:
Elsewhere…
The output of this will be:
But why? We only added ‘World’ to
myList2. WellmyList1andmyList2point to the same thing. When we didmyList1 = MyStaticClass.MyListwe didn’t get a copy of the item, just a reference to it.