2012-03-26 75 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