如何设置调试器以捕获更改变量的内容

How do I set the debugger to catch what changed the variable

我正在按照这张幻灯片和视频实施 NEH 算法: http://mams.rmit.edu.au/b5oatq61pmjl.pdf https://www.youtube.com/watch?v=TcBzEyCQBxw

我在测试期间遇到的问题是变量 Sorted_list 发生了变化,导致结果与我预期的不同: 这是我遇到问题的部分,但我不知道它改变了什么(我使用断点并观察变量 window):

for (int i = 0; i < kmsList.Count; i++)
    {
        for (int j = 0; j < kmsList[i].Length - 1; j++)
        {
            /*
            *
            *   HERE Sorted_list GET MODIFIED UNEXPECTEDLY
            */
            if (i == 0 && j == 0)
                kmsList[0][0] = Sorted_list[0][0];
            else if (i == 0)
                kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
            else if (j == 0)
                kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
        }
    }

完成实施:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FINAL_NEH
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("entre the nmbr of jobs   : ");
            string row = Console.ReadLine();
            Console.WriteLine("entre the nmbr of machines : ");
            string column = Console.ReadLine();

            int job = int.Parse(row.ToString());
            int machine = int.Parse(column.ToString());

            List<int[]> list = new List<int[]>();
            // read the nmbrs and put it in list-----------------------------------------------------  
            for (int i = 0; i < job; i++)
            {
                list.Add(new int[machine + 1]);
                for (int j = 0; j < machine; j++)
                {
                    list[i][j] = int.Parse(Console.ReadLine());
                }

                list[i][list[i].Length - 1] = int.Parse((i + 1).ToString()); //Last Elemnt Is Job Number-
            }

            // show the list----------------------------------------------------------------------------
            for (int i = 0; i < job; i++)
            {
                for (int j = 0; j < machine + 1; j++)
                {
                    Console.Write("\t" + "[" + list[i][j] + "]");
                }

                Console.WriteLine();
            }

            // sort the list------------------------------------------------------------------------------
            for (int i = 0; i < list.Count; i++)
            {
                for (int j = i + 1; j < list.Count; j++)
                {
                    int sumI = 0, sumJ = 0;

                    for (int a = 0; a < list[i].Length - 1; a++)
                    {
                        sumI += list[i][a];
                    }

                    for (int a = 0; a < list[j].Length - 1; a++)
                    {
                        sumJ += list[j][a];
                    }

                    if (sumI < sumJ)
                    {
                        int[] temp = new int[int.Parse(job.ToString())];
                        temp = list[i];
                        list[i] = list[j];
                        list[j] = temp;
                    }
                }


            }

            Console.Write("\n\n-----------------after sorting ------------------------------------\n\n");

            // shaw the list after sorting------------------------------------------
            for (int i = 0; i < job; i++)
            {
                for (int j = 0; j < machine + 1; j++)
                {
                    Console.Write("\t" + "[" + list[i][j] + "]");
                }

                Console.WriteLine();
            }



            // clculate the maxpane of the first 2 jobs---------------------------------------
            List<int[]> initMaxpane = new List<int[]>();
            initMaxpane.Add((int[])list[0].Clone());
            initMaxpane.Add((int[])list[1].Clone());

            // calculer maxspan of  first jobs..............................................
            for (int i = 0; i < initMaxpane.Count; i++)
            {
                for (int j = 0; j < initMaxpane[i].Length - 1; j++)
                {
                    if (j == 0 && i == 0)
                        initMaxpane[0][0] = list[i][j];
                    else if (i == 0)
                        initMaxpane[0][j] = (int)(initMaxpane[0][j - 1] + list[0][j]);
                    else if (j == 0)
                        initMaxpane[i][0] = (int)(initMaxpane[i - 1][0] + list[i][0]);
                }
            }

            for (int i = 1; i < initMaxpane.Count; i++)
            {
                for (int j = 1; j < initMaxpane[i].Length - 1; j++)
                {
                    if ((initMaxpane[i][j - 1] > initMaxpane[i - 1][j]))
                        initMaxpane[i][j] = (int)(initMaxpane[i][j - 1] + list[i][j]);
                    else
                        initMaxpane[i][j] = (int)(initMaxpane[i - 1][j] + list[i][j]);
                }
            }

            int Cmax = initMaxpane[initMaxpane.Count - 1][initMaxpane[initMaxpane.Count - 1].Length - 2];



            Console.WriteLine("\n\n-------the maxpane offirst jobs----------");
            for (int i = 0; i < initMaxpane.Count; i++)
            {
                for (int j = 0; j < initMaxpane[i].Length; j++)
                {
                    Console.Write("\t" + "[" + initMaxpane[i][j] + "]");
                }

                Console.WriteLine();
            }


            List<int[]> initMaxpane2 = new List<int[]>();
            initMaxpane2.Add(list.ElementAt(1));
            initMaxpane2.Add(list.ElementAt(0));

            // calculer maxspan of  first jobs reverse..............................................
            for (int i = 0; i < initMaxpane2.Count; i++)
            {
                for (int j = 0; j < initMaxpane2[i].Length - 1; j++)
                {
                    if (j == 0 && i == 0)
                        initMaxpane2[0][0] = list[i][j];
                    else if (i == 0)
                        initMaxpane2[0][j] = (int)(initMaxpane2[0][j - 1] + list[0][j]);
                    else if (j == 0)
                        initMaxpane2[i][0] = (int)(initMaxpane2[i - 1][0] + list[i][0]);
                }
            }

            for (int i = 1; i < initMaxpane2.Count; i++)
            {
                for (int j = 1; j < initMaxpane2[i].Length - 1; j++)
                {
                    if ((initMaxpane2[i][j - 1] > initMaxpane2[i - 1][j]))
                        initMaxpane2[i][j] = (int)(initMaxpane2[i][j - 1] + list[i][j]);
                    else
                        initMaxpane2[i][j] = (int)(initMaxpane2[i - 1][j] + list[i][j]);
                }
            }

            int Cmax2 = initMaxpane2[initMaxpane2.Count - 1][initMaxpane2[initMaxpane2.Count - 1].Length - 2];
            Console.WriteLine("\n\n-------the maxpane of first jobs (reverse)----------");
            for (int i = 0; i < initMaxpane2.Count; i++)
            {
                for (int j = 0; j < initMaxpane2[i].Length; j++)
                {
                    Console.Write("\t" + "[" + initMaxpane2[i][j] + "]");
                }

                Console.WriteLine();
            }

            List<int[]> MaxpaneList = new List<int[]>();
            if (Cmax > Cmax2)
            {
                MaxpaneList.Add((int[])list[1].Clone());
                MaxpaneList.Add((int[])list[0].Clone());
            }
            else
            {
                MaxpaneList.Add((int[])list[0].Clone());
                MaxpaneList.Add((int[])list[1].Clone());
            }

            List<int[]> bestSequenceList = null;
            List<int[]> kmsList = null;
            List<int[]> Sorted_list = list.ToList();
            int bestCma = 0;
            //int maxspan = 0;

            for (int jo = 2; jo < job; jo++)
            {
                for (int ins = 0; ins <= MaxpaneList.Count; ins++)
                {
                    MaxpaneList.Insert(ins, list[jo]);
                    kmsList = MaxpaneList.ToList();
                    int Cma = 0;
                    for (int i = 0; i < kmsList.Count; i++)
                    {
                        for (int j = 0; j < kmsList[i].Length - 1; j++)
                        {
                            /*
                            *
                            *   HERE Sorted_list GET MODIFIED UNEXPECTEDLY
                            */
                            if (i == 0 && j == 0)
                                kmsList[0][0] = Sorted_list[0][0];
                            else if (i == 0)
                                kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
                            else if (j == 0)
                                kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
                        }
                    }

                    for (int i = 1; i < kmsList.Count; i++)
                    {
                        for (int j = 1; j < kmsList[i].Length - 1; j++)
                        {
                            if ((kmsList[i][j - 1] > kmsList[i - 1][j]))
                                kmsList[i][j] = kmsList[i][j - 1] + Sorted_list[i][j];
                            else
                                kmsList[i][j] = kmsList[i - 1][j] + Sorted_list[i][j];
                        }
                    }

                    Cma = kmsList[kmsList.Count - 1][kmsList[kmsList.Count - 1].Length - 2];
                    Console.WriteLine("\n\n\n------- the maxpane sequence ----------");
                    for (int i = 0; i < MaxpaneList.Count; i++)
                    {
                        for (int j = 0; j < MaxpaneList[i].Length; j++)
                        {
                            Console.Write("\t" + "[" + MaxpaneList[i][j] + "]");
                        }

                        Console.WriteLine();
                    }

                    Console.WriteLine("MAX   : " + Cma + "\n\n\n");
                    if (ins == 0)
                    {
                        bestCma = Cma;
                    }

                    if (jo == 2 && ins == 0)
                    {
                        bestSequenceList = MaxpaneList.ToList();
                        bestCma = Cma;
                    }
                    else
                    {
                        if (bestCma > Cma)
                        {
                            bestSequenceList = MaxpaneList.ToList();
                            bestCma = Cma;
                        }
                    }

                    MaxpaneList.RemoveAt(ins);
                }

                MaxpaneList = bestSequenceList.ToList();
            }

            Console.ReadLine();
        }
    }
}

当您从另一个容器创建 List<>(或任何其他容器)时(就像您调用 list.ToList() 时所做的那样),您不会创建容器中所有元素的副本。您创建了对正在复制的列表中的项目的新引用。用 CS 的说法是浅拷贝而不是深拷贝。

所以,如果你这样做:

        int[] ia = new[] {0, 1, 2, 3, 4};
        int[] ib = new[] {5, 6, 7, 8, 9};
        List<int[]> la = new List<int[]>() { ia, ib };
        List<int[]> lb = la.ToList();

两个列表引用相同的两个数组,如果您像这样更改一个数组:

        la[1][4] = 10;

那么 lb[1][4] 也将是 10,因为两个列表各自包含相同的数组。复制列表不会复制列表中的元素。

问题出在以下代码(片段):

List<int[]> Sorted_list = list.ToList();

ToList 将创建一个新列表,但由于在本例中 int[] 是引用类型,因此新列表将包含对与原始列表相同的数组的引用。

更新新列表中引用的(数组的)值也会影响原始列表中的等效值。

kmsList[0][0] = Sorted_list[0][0];

解决方案是创建 'list' 及其项(在本例中为 int[])的真实副本:

List<int[]> Sorted_list  = list.ConvertAll(myArray => (int[])myArray.Clone());

这段代码将列表中的所有数组克隆到一个新变量Sorted_list。

解释值类型和引用类型之间差异的有用 link 是:https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx

引用类型

引用类型包含指向保存数据的另一个内存位置的指针。

引用类型包括以下:

  • 字符串
  • 所有数组,即使它们的元素是值类型Class
  • 类型,例如表格
  • 代表