2

私のコードを見て、どこが間違っているのかを確認していただけませんか。基本的に、「UserFile」タイプ(自分のオブジェクトタイプ)のオブジェクトを作成し、その2つのインスタンスを作成し、そのオブジェクトのコンストラクター内で静的クラスメソッドを呼び出しています。オブジェクトコンストラクターが呼び出された後、2番目のインスタンスが最初のインスタンスを上書きすることを除いて、すべてがうまくいきます。私はプログラムをステップスルーし、完全に混乱しています。私はここで非常に明白な何かを見逃しているような気がします。

これがインスタンスを作成するフォームのボタンです

    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メソッドです。

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

1 に答える 1

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!

ここで行われるのは、メンバー変数fileIndividualsfileFamiliesあり、コピーではなく静的クラスのプロパティとプロパティにfileHead設定されます(これらはクラスであり、値型ではないため)。したがって、次回は静的プロパティが更新(上書き)されると呼ばれますが、の前のインスタンスは同じ静的プロパティergoを指し、同じデータを持ちます。individualsfamiliesheadReadFromFileReadFromFile.Read()ReadFromFileUserFilefile1file2

では、これをどのように修正しますか?2つのオプション:

  1. 静的ReadFromFileなものではなく、クラスを作成してインスタンス化します。コンストラクターで新しいインスタンスを作成し、静的プロパティをUserFile使用しないでください。
  2. individualsfamiliesおよびheadのコンストラクターでデータのコピーを作成しますUserFile。各項目を「foreach」して、新しい辞書にコピーします。

簡単な説明:

オブジェクトがクラスの場合に割り当て(C#では=文字)を実行すると、ターゲットには右側に「ポインター」(参照)が割り当てられます。値型の場合はコピーされます。辞書はクラスであるため、コピーではなくポインタを取得します。

コード内の図:

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 

しかし、なぜ?に「World」を追加しただけmyList2です。さて、同じことmyList1myList2 指してください。私たちが行ったとき、私たちはアイテム のコピーmyList1 = MyStaticClass.MyListを手に入れませんでした、ただそれへの参照です。

于 2012-03-26T23:42:08.693 に答える