如何清理做几乎相同事情的长 if else 语句

How to cleanup long if else statements that do almost the same thing

所以我有这么长的 C# 代码(请原谅我是初学者,而且它很乱),但我基本上想重复所有步骤,但如果“-o”&a,我也会将文本输出到文件中文件名 (example.txt) 在命令行参数中给出。

目前,我已经从第一个 if 语句复制了 else 语句中的所有代码以及用于输出到文件的附加代码。

有没有办法解决这个问题/不必重复它而只需参考它然后添加额外的步骤?

namespace testapp
{
    class Program
    {
        static void Main(string[] args)
        {

            string inputFile = args[0];
            string inputPlane = args[1];
            string inputTime = args[2];

            // Check for output flag "-o"
            bool checkForOutput = Array.Exists(args, element => element == "-o");

            if (File.Exists(inputFile) && checkForOutput == true)
            {
                //================== Get inputFile formatted ==================
                List<string> lines = File.ReadAllLines(inputFile).ToList(); // Read text and put into list
                string words = lines.Aggregate((i, j) => i + " " + j).ToString(); // Split into sentences
                string[] splitWords = words.Split(); // Each individual word
                int listLength = lines.Count; // Count total lines
                string[] stations = new string[listLength];


                //================== Get plane file formatted ==================
                List<string> planeLines = File.ReadAllLines(inputPlane).ToList(); // Read text and put into list
                string planeElements = planeLines.Aggregate((i, j) => i + " " + j).ToString();
                string[] stringPlaneSpec = planeElements.Split();
                int[] intPlaneSpec = new int[stringPlaneSpec.Length];
                for (int n = 0; n < stringPlaneSpec.Length; n++)
                    intPlaneSpec[n] = int.Parse(stringPlaneSpec[n]);


                //================== Store station Details ==================
                Station[] stationDetails = new Station[listLength];
                int stationCounter = 0;
                while (stationCounter < listLength)
                {
                    for (int i = 0; i < splitWords.Length; i += 3)
                    {
                        stationDetails[stationCounter] = new Station(splitWords[i], Convert.ToInt32(splitWords[i + 1]), Convert.ToInt32(splitWords[i + 2]));
                        stationCounter++;
                    }
                }
                List<Station> stationNamesList = stationDetails.ToList();


                //================== Store station names ==================

                string[] names = new string[listLength];
                int nameCounter = 0;
                while (nameCounter < listLength)
                {
                    for (int i = 0; i < splitWords.Length; i += 3)
                    {
                        names[nameCounter] = (splitWords[i]);
                        nameCounter++;
                    }
                }
                //================== Store plane details ==================
                Plane plane1 = new Plane(intPlaneSpec[0], intPlaneSpec[1], intPlaneSpec[2], intPlaneSpec[3], intPlaneSpec[4]);

                //================== Store distance totals between position [i] & [i + 1] ==================

                double[] distanceTotal = new double[listLength];

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {
                    distanceTotal[i] = Math.Round(Station.Distance((stationDetails[i].XValue),
                    (stationDetails[i + 1].XValue),
                    (stationDetails[i].YValue),
                    (stationDetails[i + 1].YValue)), 4);
                }
                int lastStation = stationDetails.GetUpperBound(0);

                // Store last distance total
                distanceTotal[lastStation] = Math.Round(Station.Distance((stationDetails[lastStation].XValue),
                (stationDetails[0].XValue),
                (stationDetails[lastStation].YValue),
                (stationDetails[0].YValue)), 4);

                //================== Setup list for storing times ==================

                DateTime startTime = DateTime.Parse(inputTime);
                List<DateTime> temporaryTimes = new List<DateTime>();
                temporaryTimes.Add(startTime); // Add initial value "23:00
                List<string> timeStrings = new List<string>();

                for (int i = 0; i < distanceTotal.Length; i++)
                {
                    temporaryTimes.Add(startTime.AddMinutes((Tour.CalTime(distanceTotal[i], plane1))));
                    string stringVersion = startTime.ToString(@"hh\:mm");
                    timeStrings.Add(stringVersion);
                    startTime = (startTime.AddMinutes((Tour.CalTime(distanceTotal[i], plane1))));
                }

                //================== Store total duration of trip ==================
                int last = (temporaryTimes.Count);
                TimeSpan totalTime = temporaryTimes[last - 1] - temporaryTimes[0];

                //================== Setup list for storing tour names ==================
                List<string> tourNames = new List<string>();

                //================== Output to Console Window & file ==================
                // Setup output file
                string outputFile = args[4];
                FileStream outFile = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
                StreamWriter writer = new StreamWriter(outFile);

                Console.WriteLine("Reading input from {0}", inputFile);
                if (totalTime.Days >= 1)
                {
                    Console.WriteLine("Tour time: {0} days {1} hours {2} minutes", totalTime.Days, totalTime.Hours, totalTime.Minutes);

                }
                else
                {
                    Console.WriteLine("Tour time: {0} hours {1} minutes", totalTime.Hours, totalTime.Minutes);
                }

                Console.WriteLine("Optimising tour length: Level 1...");
                Console.WriteLine("Tour length: {0}", distanceTotal.Sum()); // sum of trip
                writer.WriteLine(distanceTotal.Sum()); // write sum to output file

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {
                    Console.WriteLine("{0}\t->\t{1}\t{2}",
                    stationDetails[i].StationName.Substring(0, 2),
                    stationDetails[i + 1].StationName.Substring(0, 2),
                    distanceTotal[i]);

                    // Store names to tour names
                    tourNames.Add(stationDetails[i].StationName.Substring(0, 2));
                    tourNames.Add(stationDetails[i + 1].StationName.Substring(0, 2));

                    writer.WriteLine("{0}\t->\t{1}\t{2}",
                    stationDetails[i].StationName.Substring(0, 2),
                    stationDetails[i + 1].StationName.Substring(0, 2),
                    Math.Round(Station.Distance((stationDetails[i].XValue),
                    (stationDetails[i + 1].XValue),
                    (stationDetails[i].YValue),
                    (stationDetails[i + 1].YValue)), 4));

                }
                // Write Last distance to console
                Console.WriteLine("{0}\t->\t{1}\t{2}",
                stationDetails[lastStation].StationName.Substring(0, 2),
                stationDetails[0].StationName.Substring(0, 2), distanceTotal[lastStation]);

                //================== Store tour Details in object ==================
                Tour tour1 = new Tour(4.2, plane1, tourNames, temporaryTimes, totalTime);

                ////================== Algorithm ==================

                //// Empty tour with post office initially added
                List<Station> stationsLeft = stationDetails.ToList();
                List<Station> fuckingDone = Tour.SimpleHueristic(stationsLeft);

                foreach (Station var in fuckingDone)
                {
                    Console.WriteLine("{0} {1} {2}", var.StationName, var.XValue, var.YValue);
                }

                // Write last distance to output file
                writer.WriteLine("{0}\t->\t{1}\t{2}",
                stationDetails[lastStation].StationName.Substring(0, 2),
                stationDetails[0].StationName.Substring(0, 2),
                Math.Round(Station.Distance((stationDetails[lastStation].XValue),
                (stationDetails[0].XValue),
                (stationDetails[lastStation].YValue),
                (stationDetails[0].YValue)), 4));

                // Close output file
                writer.Close();
                outFile.Close();
            }


            //================== END OF IF STATEMENT - NEXT SECTION OF CODE (NEEDS TO BE THE SAME) ================

            else if (File.Exists(inputFile) && checkForOutput == false)
            {
                //================== Get inputFile formatted ==================
                List<string> lines = File.ReadAllLines(inputFile).ToList(); // Read text and put into list
                string words = lines.Aggregate((i, j) => i + " " + j).ToString(); // Split into sentences
                string[] splitWords = words.Split(); // Each individual word
                int listLength = lines.Count; // Count total lines
                string[] stations = new string[listLength];

                //================== Get plane file formatted ==================
                List<string> planeLines = File.ReadAllLines(inputPlane).ToList(); // Read text and put into list
                string planeElements = planeLines.Aggregate((i, j) => i + " " + j).ToString();
                string[] stringPlaneSpec = planeElements.Split();
                int[] intPlaneSpec = new int[stringPlaneSpec.Length];
                for (int n = 0; n < stringPlaneSpec.Length; n++)
                    intPlaneSpec[n] = int.Parse(stringPlaneSpec[n]);

                //================== Store station Details ==================

                Station[] stationDetails = new Station[listLength];
                int stationCounter = 0;
                while (stationCounter < listLength)
                {
                    for (int i = 0; i < splitWords.Length; i += 3)
                    {
                        stationDetails[stationCounter] = new Station(splitWords[i], Convert.ToInt32(splitWords[i + 1]), Convert.ToInt32(splitWords[i + 2]));
                        stationCounter++;
                    }
                }

                //================== Store plane details ==================
                Plane plane1 = new Plane(intPlaneSpec[0], intPlaneSpec[1], intPlaneSpec[2], intPlaneSpec[3], intPlaneSpec[4]);

                //================== Store time details ==================
                DateTime newTime = DateTime.Parse(inputTime);
                string formatedTime = newTime.ToString("HH:mm");

                //================== Store distance totals between position [i] & [i + 1] ==================
                double[] distanceTotal = new double[listLength];

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {
                    distanceTotal[i] = Math.Round(Station.Distance((stationDetails[i].XValue),
                    (stationDetails[i + 1].XValue),
                    (stationDetails[i].YValue),
                    (stationDetails[i + 1].YValue)), 4);
                }

                int lastStation = stationDetails.GetUpperBound(0);

                // Store last distance total
                distanceTotal[lastStation] = Math.Round(Station.Distance((stationDetails[lastStation].XValue),
                (stationDetails[0].XValue),
                (stationDetails[lastStation].YValue),
                (stationDetails[0].YValue)), 4);

                //================== Setup list for storing times ==================
                List<DateTime> temporaryTimes = new List<DateTime>();

                //================== Setup list for storing tour names ==================
                List<string> tourNames = new List<string>();

                //================== Output to only Console ==================
                Console.WriteLine("Reading input from {0}", inputFile);
                Console.WriteLine("Optimising tour length: Level 1...");
                Console.WriteLine("Tour length: {0}", distanceTotal.Sum()); // sum of trip

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {

                    Console.WriteLine("{0}\t->\t{1}\t{2}",
                    stationDetails[i].StationName.Substring(0, 2),
                    stationDetails[i + 1].StationName.Substring(0, 2),
                    distanceTotal[i]);
                }

                // Output last distance back to post office
                Console.WriteLine("{0}\t->\t{1}\t{2}",
                stationDetails[lastStation].StationName.Substring(0, 2),
                stationDetails[0].StationName.Substring(0, 2), distanceTotal[lastStation]);
            }
            else
            {
                //========== Display error message if input is incorrect ============

                Console.WriteLine("Invalid Input");
            }

            Console.ReadLine();
        }
    }
}

else 语句基本上做同样的事情,只是没有将结果写入文件。

代码太多了。

您的代码清楚地表明,只要文件存在,大多数步骤都是通用的。您可以 re-structure 您的代码如下:

  1. 先执行验证
  2. 执行常见步骤
  3. 根据checkForOutput标志执行特定步骤

我建议将您的代码分解为多个方法,每个方法执行特定的操作。这样,如果您的方法名称是 self-describing.

,您就不需要添加条形注释来解释您想要做什么

我已经通过重构方法 GetInputFileFormattedGetSplitWordsGetPlaneFileFormattedGetStationDetails 为您完成了部分工作。我把剩下的练习留给你。

我通常建议我的开发人员的另一件事是清楚地在顶部执行验证。请注意,我首先检查文件是否存在,如果失败则立即 short-circuiting 执行。这删除了一层嵌套,并立即明确您的意图,即提供的文件路径在执行任何操作之前必须存在。

static void Main(string[] args)
        {
            string inputFile = args[0];
            string inputPlane = args[1];
            string inputTime = args[2];

            // Check for output flag "-o"
            bool checkForOutput = Array.Exists(args, element => element == "-o");

            if(!File.Exists(inputFile))
            {
                Console.WriteLine("Invalid Input");
                return;
            }

            var inputFileLines = GetInputFileFormatted(inputFile);
            var splitWords = GetSplitWords(inputFileLines);
            var planeFileLines = GetPlaneFileFormatted(inputPlane);
            var stationDetails = GetStationDetails(inputFileLines.Count, splitWords);

            if (checkForOutput == true)
            {
                //================== Store station names ==================

                string[] names = new string[listLength];
                int nameCounter = 0;
                while (nameCounter < listLength)
                {
                    for (int i = 0; i < splitWords.Length; i += 3)
                    {
                        names[nameCounter] = (splitWords[i]);
                        nameCounter++;
                    }
                }
                //================== Store plane details ==================
                Plane plane1 = new Plane(intPlaneSpec[0], intPlaneSpec[1], intPlaneSpec[2], intPlaneSpec[3], intPlaneSpec[4]);

                //================== Store distance totals between position [i] & [i + 1] ==================

                double[] distanceTotal = new double[listLength];

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {
                    distanceTotal[i] = Math.Round(Station.Distance((stationDetails[i].XValue),
                    (stationDetails[i + 1].XValue),
                    (stationDetails[i].YValue),
                    (stationDetails[i + 1].YValue)), 4);
                }
                int lastStation = stationDetails.GetUpperBound(0);

                // Store last distance total
                distanceTotal[lastStation] = Math.Round(Station.Distance((stationDetails[lastStation].XValue),
                (stationDetails[0].XValue),
                (stationDetails[lastStation].YValue),
                (stationDetails[0].YValue)), 4);

                //================== Setup list for storing times ==================

                DateTime startTime = DateTime.Parse(inputTime);
                List<DateTime> temporaryTimes = new List<DateTime>();
                temporaryTimes.Add(startTime); // Add initial value "23:00
                List<string> timeStrings = new List<string>();

                for (int i = 0; i < distanceTotal.Length; i++)
                {
                    temporaryTimes.Add(startTime.AddMinutes((Tour.CalTime(distanceTotal[i], plane1))));
                    string stringVersion = startTime.ToString(@"hh\:mm");
                    timeStrings.Add(stringVersion);
                    startTime = (startTime.AddMinutes((Tour.CalTime(distanceTotal[i], plane1))));
                }

                //================== Store total duration of trip ==================
                int last = (temporaryTimes.Count);
                TimeSpan totalTime = temporaryTimes[last - 1] - temporaryTimes[0];

                //================== Setup list for storing tour names ==================
                List<string> tourNames = new List<string>();

                //================== Output to Console Window & file ==================
                // Setup output file
                string outputFile = args[4];
                FileStream outFile = new FileStream(outputFile, FileMode.Create, FileAccess.Write);
                StreamWriter writer = new StreamWriter(outFile);

                Console.WriteLine("Reading input from {0}", inputFile);
                if (totalTime.Days >= 1)
                {
                    Console.WriteLine("Tour time: {0} days {1} hours {2} minutes", totalTime.Days, totalTime.Hours, totalTime.Minutes);

                }
                else
                {
                    Console.WriteLine("Tour time: {0} hours {1} minutes", totalTime.Hours, totalTime.Minutes);
                }

                Console.WriteLine("Optimising tour length: Level 1...");
                Console.WriteLine("Tour length: {0}", distanceTotal.Sum()); // sum of trip
                writer.WriteLine(distanceTotal.Sum()); // write sum to output file

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {
                    Console.WriteLine("{0}\t->\t{1}\t{2}",
                    stationDetails[i].StationName.Substring(0, 2),
                    stationDetails[i + 1].StationName.Substring(0, 2),
                    distanceTotal[i]);

                    // Store names to tour names
                    tourNames.Add(stationDetails[i].StationName.Substring(0, 2));
                    tourNames.Add(stationDetails[i + 1].StationName.Substring(0, 2));

                    writer.WriteLine("{0}\t->\t{1}\t{2}",
                    stationDetails[i].StationName.Substring(0, 2),
                    stationDetails[i + 1].StationName.Substring(0, 2),
                    Math.Round(Station.Distance((stationDetails[i].XValue),
                    (stationDetails[i + 1].XValue),
                    (stationDetails[i].YValue),
                    (stationDetails[i + 1].YValue)), 4));

                }
                // Write Last distance to console
                Console.WriteLine("{0}\t->\t{1}\t{2}",
                stationDetails[lastStation].StationName.Substring(0, 2),
                stationDetails[0].StationName.Substring(0, 2), distanceTotal[lastStation]);

                //================== Store tour Details in object ==================
                Tour tour1 = new Tour(4.2, plane1, tourNames, temporaryTimes, totalTime);

                ////================== Algorithm ==================

                //// Empty tour with post office initially added
                List<Station> stationsLeft = stationDetails.ToList();
                List<Station> fuckingDone = Tour.SimpleHueristic(stationsLeft);

                foreach (Station var in fuckingDone)
                {
                    Console.WriteLine("{0} {1} {2}", var.StationName, var.XValue, var.YValue);
                }

                // Write last distance to output file
                writer.WriteLine("{0}\t->\t{1}\t{2}",
                stationDetails[lastStation].StationName.Substring(0, 2),
                stationDetails[0].StationName.Substring(0, 2),
                Math.Round(Station.Distance((stationDetails[lastStation].XValue),
                (stationDetails[0].XValue),
                (stationDetails[lastStation].YValue),
                (stationDetails[0].YValue)), 4));

                // Close output file
                writer.Close();
                outFile.Close();
            }


            //================== END OF IF STATEMENT - NEXT SECTION OF CODE (NEEDS TO BE THE SAME) ================

            else if (checkForOutput == false)
            {
                //================== Store plane details ==================
                Plane plane1 = new Plane(intPlaneSpec[0], intPlaneSpec[1], intPlaneSpec[2], intPlaneSpec[3], intPlaneSpec[4]);

                //================== Store time details ==================
                DateTime newTime = DateTime.Parse(inputTime);
                string formatedTime = newTime.ToString("HH:mm");

                //================== Store distance totals between position [i] & [i + 1] ==================
                double[] distanceTotal = new double[listLength];

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {
                    distanceTotal[i] = Math.Round(Station.Distance((stationDetails[i].XValue),
                    (stationDetails[i + 1].XValue),
                    (stationDetails[i].YValue),
                    (stationDetails[i + 1].YValue)), 4);
                }

                int lastStation = stationDetails.GetUpperBound(0);

                // Store last distance total
                distanceTotal[lastStation] = Math.Round(Station.Distance((stationDetails[lastStation].XValue),
                (stationDetails[0].XValue),
                (stationDetails[lastStation].YValue),
                (stationDetails[0].YValue)), 4);

                //================== Setup list for storing times ==================
                List<DateTime> temporaryTimes = new List<DateTime>();

                //================== Setup list for storing tour names ==================
                List<string> tourNames = new List<string>();

                //================== Output to only Console ==================
                Console.WriteLine("Reading input from {0}", inputFile);
                Console.WriteLine("Optimising tour length: Level 1...");
                Console.WriteLine("Tour length: {0}", distanceTotal.Sum()); // sum of trip

                for (int i = 0; i < stationDetails.Length - 1; i++)
                {

                    Console.WriteLine("{0}\t->\t{1}\t{2}",
                    stationDetails[i].StationName.Substring(0, 2),
                    stationDetails[i + 1].StationName.Substring(0, 2),
                    distanceTotal[i]);
                }

                // Output last distance back to post office
                Console.WriteLine("{0}\t->\t{1}\t{2}",
                stationDetails[lastStation].StationName.Substring(0, 2),
                stationDetails[0].StationName.Substring(0, 2), distanceTotal[lastStation]);
            }
            else
            {
                //========== Display error message if input is incorrect ============

                Console.WriteLine("Invalid Input");
            }

            Console.ReadLine();            
        }

        static List<string> GetInputFileFormatted(string inputFile)
        {
            List<string> lines = File.ReadAllLines(inputFile).ToList(); // Read text and put into list
            return lines;
        }

        static string[] GetSplitWords(List<string> inputFileLines)
        {
            string words = inputFileLines.Aggregate((i, j) => i + " " + j).ToString(); // Split into sentences
            return words.Split(); // Each individual word
        }

        static List<string> GetPlaneFileFormatted(string inputPlane)
        {
            List<string> planeLines = File.ReadAllLines(inputPlane).ToList(); // Read text and put into list
            string planeElements = planeLines.Aggregate((i, j) => i + " " + j).ToString();
            string[] stringPlaneSpec = planeElements.Split();
            int[] intPlaneSpec = new int[stringPlaneSpec.Length];
            for (int n = 0; n < stringPlaneSpec.Length; n++)
                intPlaneSpec[n] = int.Parse(stringPlaneSpec[n]);
            return planeLines;
        }

        static Station[] GetStationDetails(int inputFileLinesLength, string[] splitWords)
        {
            Station[] stationDetails = new Station[inputFileLinesLength];
            int stationCounter = 0;
            while (stationCounter < inputFileLinesLength)
            {
                for (int i = 0; i < splitWords.Length; i += 3)
                {
                    stationDetails[stationCounter] = new Station(splitWords[i], Convert.ToInt32(splitWords[i + 1]), Convert.ToInt32(splitWords[i + 2]));
                    stationCounter++;
                }
            }
            return stationDetails;
        }