2012-03-26 74 views
1

我想知道你是否可以看看我的代码,看看我出错了。基本上,我创建了一个类型为“UserFile”的对象(我自己的对象类型),并创建它的两个实例,并在该对象的构造函数中调用静态类方法。除了第二个实例在调用对象构造函数之后覆盖第一个实例之外,它们一切顺利。我已经通过了该计划,并且感到非常困惑。我在这里感受到错失很明显的感觉。对象实例覆盖另一个实例,但我不明白为什么

下面是创建实例

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

这里窗体上的按钮时的userfile的类构造函数

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

这里被称为由userfile的所述ReadFromFile方法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>[[email protected]]+)(?: *)(?<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(); 
     } 
    } 
} 

回答

3

的问题是在ReadFromFile类以下这些静态属性,如果我被“覆盖”假设你的意思是UserFile点的相同的数据这两种情况下:

public static Dictionary<int, Family> families = new Dictionary<int, Family>(); 
public static Dictionary<int, Individual> individuals = new Dictionary<int, Individual>(); 
public static Header head; 

的问题出在构造函数UserFile关于使用静态属性。

ReadFromFile.Read(_dir); 
    fileIndividuals = ReadFromFile.individuals; // <-- Uh-oh! 
    fileFamilies = ReadFromFile.families;  // <-- Uh-oh! 
    fileHead = ReadFromFile.head;    // <-- Uh-oh! 

这里会发生什么是成员变量fileIndividualsfileFamiliesfileHead设置为individualsfamilieshead特性对静态ReadFromFile参考不是副本(因为它们是类而不是值类型)。所以下次ReadFromFile.Read()被称为ReadFromFile上的静态属性被更新(覆盖),但是之前的UserFile实例只是指向相同的静态属性,ergo file1file2将具有相同的数据。

那么你会如何解决这个问题?两种选择:

  1. 使ReadFromFile和实例类,而不是一个静态的。在UserFile构造函数中构造一个新实例,并且不要使用任何静态属性。
  2. individualsfamilieshead中的数据拷贝到UserFile的构造函数中。通过每个项目“foreach”,并将其复制到一个新的字典中。

简单的解释:

当执行一个assign(在C#=字符),如果对象是类,则目标被分配一个“指针”(参考)向右手边。如果它是一个值类型,它将被复制。 Dictionary是一个类,所以你得到一个指针而不是副本。

插图代码:

public static class MyStaticClass 
{ 
    public static List<string> MyList = new List<string> 
} 

别处......

public void MyMethod() 
{ 
    List<string> myList1 = MyStaticClass.MyList; 
    List<string> myList2 = MyStaticClass.MyList; 

    myList1.Add("Hello"); // Add to first list 
    myList2.Add("World"); // Add to second list 

    foreach(string item in myList1) // print all items in the second list 
    { 
     Console.WriteLine("List 1: " + item); 
    } 

    foreach(string item in myList2) // print all items in the second list 
    { 
     Console.WriteLine("List 2: " + item); 
    } 
} 

这样做的结果应该是:

List 1: Hello 
List 1: World 
List 2: Hello 
List 2: World 

但是,为什么?我们只添加了'世界'到myList2。那么myList1myList2到同样的事情。当我们做了myList1 = MyStaticClass.MyList我们没有得到拷贝的项目,只是参考它。

+1

谢谢,但我想知道你是否可以用更基本的术语解释它?我正在考虑第二个选项 – user1290653 2012-03-26 23:51:47

+1

完成:)你真的想要选项#1的方式。 – 2012-03-27 00:17:17

+0

我知道,但是当我停止ReadFromFile类是静态的,没有任何工作。我忘记了我现在静止的原因 – user1290653 2012-03-27 00:19:54