简体   繁体   English

如何避免多次重复类似的代码?

[英]How to avoid repeating a similar code several times?

I'm doing a Subway restaurant like console application. 我正在做类似控制台应用程序的Subway餐厅。 It's heavily dependent on loops, and there's a specific kind of loop I've repeated lots of times. 它在很大程度上取决于循环,并且我已经重复了很多次特定的循环。

Basically, I write the options, then I make the cursor be over the initial option. 基本上,我编写选项,然后使光标位于初始选项上方。 Whatever option the user presses enter while the cursor is over it, is the selected option. 用户将光标悬停在Enter上方的任何选项均是所选选项。

Here's the first part of the code (it's kinda big, but that's why I'm asking here after all): 这是代码的第一部分(相当大,但这就是为什么我要在这里询问的原因):

static int Row = 0; //To set the row of the cursor

    static void Menu()
    {
        Console.WriteLine("Hi, welcome to Subway!"); //Line 0
        Console.WriteLine(); //Line 1

        //Bread Selection
        string[] breadOptions =
        {
                        "Hearty Italian",       //Element 0
                        "9-Grain Honey Oat",    //Element 1
                        "Jalapeno Cheese",      //Element 2
                        "Monterey Cheddar",     //Element 3
                        "Parmesan Oregano",     //Element 4
                        "Roasted Garlic",       //Element 5
                        "Rosemary & Sea Salt",  //Element 6
                        "Rye Bread",            //Element 7
                        "Gluten-Free Bread",    //Element 8
        };

        Console.WriteLine("Choose you bread!"); //Line 2
        Console.WriteLine("[ ]" + breadOptions[0]); //Line 3
        Console.WriteLine("[ ]" + breadOptions[1]); //Line 4
        Console.WriteLine("[ ]" + breadOptions[2]); //Line 5
        Console.WriteLine("[ ]" + breadOptions[3]); //Line 6
        Console.WriteLine("[ ]" + breadOptions[4]); //Line 7
        Console.WriteLine("[ ]" + breadOptions[5]); //Line 8
        Console.WriteLine("[ ]" + breadOptions[6]); //Line 9
        Console.WriteLine("[ ]" + breadOptions[7]); //Line 10
        Console.WriteLine("[ ]" + breadOptions[8]); //Line 11

        Row = 3; //set the row to the first bread option
        int currentBread = 0; //a couter to keep track of the bread
        ConsoleKeyInfo breadKey = new ConsoleKeyInfo();

        do
        {   //Loop that goes with the cursor through the menu items
            for (Row = 3; Row < breadOptions.Length + 3; Row++)
            {
                //Highlight the current bread with the cursor in the box
                if (currentBread == Row - 3)
                    Console.SetCursorPosition(1, Row);
            }

            //reads the key
            breadKey = Console.ReadKey();
            switch (breadKey.Key)
            {
                case ConsoleKey.DownArrow:
                    //if the current item is the last one in the array, reset the counter.
                    if (currentBread == breadOptions.Length - 1)
                        //-1 because currentBread follows the array, and array starts at 0
                        //but the array lengh doensn't start at 0. 0 is an empty array
                        currentBread = 0;
                    //otherwise, add one to the counter
                    else
                        currentBread++;
                    break;

                case ConsoleKey.UpArrow:
                    //if the user presses Up in the first option, it goes to the last
                    if (currentBread == 0)
                        currentBread = breadOptions.Length - 1;
                    //otherwise, remove one from the counter
                    else
                        currentBread--;
                    break;
            }

        }
        //keep looping until the user presses enter
        while (breadKey.Key != ConsoleKey.Enter);

        Console.SetCursorPosition(0, 12); //set the cursor back to the next line after the last Console.WriteLine

        //make a string to store the selected bread and make it be the selected bread
        string bread = breadOptions[currentBread];

And, this do-while loop is repeated again several times, here's another example: 而且,此do-while循环再次重复了几次,这是另一个示例:

//Bread Size
        string[] sizeOptions = { "6-inches", "Footlong"};

        Console.WriteLine(); //Line 12
        Console.WriteLine("Choose a bread size."); //Line 13
        Console.WriteLine("[ ]" + sizeOptions[0]); //Line 14
        Console.WriteLine("[ ]" + sizeOptions[1]); //Line 15

        Row = 14;
        int currentSize = 0;
        ConsoleKeyInfo sizeKey = new ConsoleKeyInfo();

        do
        {
            for (Row = 14; Row < sizeOptions.Length + 14; Row++)
            {
                if (currentSize == Row - 14)
                    Console.SetCursorPosition(1, Row);
            }

            sizeKey = Console.ReadKey();
            switch (sizeKey.Key)
            {
                case ConsoleKey.DownArrow:
                    if (currentSize == sizeOptions.Length - 1)
                        currentSize = 0;
                    else
                        currentSize++;
                    break;
                case ConsoleKey.UpArrow:
                    if (currentSize == 0)
                        currentSize = sizeOptions.Length - 1;
                    else
                        currentSize--;
                    break;
            }
        } while (sizeKey.Key != ConsoleKey.Enter);

        Console.SetCursorPosition(0, 16);

        string size = sizeOptions[currentSize];

I was wondering if there's a way to not write this loop every time I need to choose an option. 我想知道是否有一种方法可以在每次需要选择一个选项时都不编写此循环。

You can use a method to do this: 您可以使用一种方法来做到这一点:

    int GetOption(int startRow, string[] options)
    {
        int currentOption = 0;
        ConsoleKeyInfo sizeKey = new ConsoleKeyInfo();

        do
        {
            for (int i = startRow; i < options.Length + startRow; i++)
            {
                if (currentOption == i - startRow)
                    Console.SetCursorPosition(1, i);
            }

            sizeKey = Console.ReadKey();
            switch (sizeKey.Key)
            {
                case ConsoleKey.DownArrow:
                    if (currentOption == options.Length - 1)
                        currentOption = 0;
                    else
                        currentOption++;
                    break;
                case ConsoleKey.UpArrow:
                    if (currentOption == 0)
                        currentOption = options.Length - 1;
                    else
                        currentOption--;
                    break;
            }
        } while (sizeKey.Key != ConsoleKey.Enter);

        return currentOption;
    }

Usage: 用法:

    string[] sizeOptions = { "6-inches", "Footlong"};
    Console.WriteLine(); //Line 12
    Console.WriteLine("Choose a bread size."); //Line 13
    Console.WriteLine("[ ]" + sizeOptions[0]); //Line 14
    Console.WriteLine("[ ]" + sizeOptions[1]); //Line 15

    Row = 14;
    int currentSize = GetOption(Row, sizeOptions);
    Console.SetCursorPosition(0, 16);
    string size = sizeOptions[currentSize];

I can't test it right now, but I hope it helps you! 我目前无法测试,但希望对您有所帮助!

Take one of the chunks of the code which you want to re-use and move it into a new method with no parameters. 提取要重用的代码块之一,然后将其移动到没有参数的新方法中。 Like the bit where you write out the options. 就像您写出选项的地方一样。

Ask yourself what is in that method which the other scenario doesn't want to be like that. 问自己,该方法中的什么是其他情况所希望的。 In the list of options scenario, the thing which varies from one place to another is the actual list of things. 在选项列表场景中,从一个地方到另一个地方不同的事物是事物的实际列表。 So we need to turn that thing into a variable (so named because the value can vary ). 因此,我们需要将其转换为变量(之所以命名,是因为其值可以变化 )。 Specifically, if you make the list of things a parameter to the method, then you can call that method from each different place, passing the relevant list. 具体来说,如果将事物列表作为方法的参数,则可以从每个不同的地方调用该方法,并传递相关列表。

Note that by doing this, it can cause you other problems to overcome. 请注意,这样做可能会导致您解决其他问题。 For example, where you print the list, you are currently hard coding each index that you want to print, so you need to find a more flexible way of doing that - a way of listing all the items in a collection, regardless how many there are. 例如,在打印列表的位置,当前正在对要打印的每个索引进行硬编码,因此您需要找到一种更灵活的方式-列出集合中所有项目的方法,无论其中有多少个项目是。 Try looking up foreach as a way of doing this. 尝试查找foreach作为一种方法。

Moving code from one place to another to make it better is called refactoring, and is a really important skill to learn in software development. 将代码从一个地方移到另一个地方以使其变得更好称为重构,这是在软件开发中学习的一项非常重要的技能。 I have only shown one of the kinds of problems that occurs when refactoring, but it's a big topic. 我只展示了重构时发生的一种问题,但这是一个大话题。 Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM