如何压缩相同的重复Else If语句

时间:2018-12-03 02:40:08

标签: c# if-statement coding-efficiency

我正在尝试一些简单的程序,用户可以使用基本的ReadLine输入进行导航。在输入过程中的任何给定时间,无论环境如何,总是可以访问几个命令,这是一个示例:

else if(input.ToLower() == "exit" || input.ToLower() == "leave")
{
    Console.Clear();
    ExitProgram.ExitProg();
    calcInput = false;
}
else if(input.ToLower() == "back" || input.ToLower() == "menu")
{
    TxtFun.CTxt("Returning to previous menu.");
    Console.ReadLine();
    Console.Clear();
    calcInput = false;
    calcLoop = false;
}
else
{
    TxtFun.CTxt("Invalid input.");
    Console.ReadLine();
    Console.Clear();

    calcInput = false;
}

以上是2如果每次都重复其他语句,则要求用户输入,然后进行检查。当我多次嵌套用户输入时,这会变得很沉重。

我的问题是,是否有一种方法可以将这些重复的其他If语句压缩为一个函数或一个单独的类,以节省时间和(大量)空间,那么将其有效地插入If /如果是其他分支?

(((如果有一种方法可以在返回“无效输入”的末尾包含重复出现的“其他”,但这不是主要问题或目标,则奖励点))

2 个答案:

答案 0 :(得分:2)

在实现REPL接口时,我做了一些不同的事情。

使用Dictionary<string, Func<string, string>>(实际上,我使用的类封装了实际的FuncAction以及一个描述,该描述可用于帮助应用程序的可用性生成带有字符串比较的help文本),该字符串忽略大小写并将期望的输入添加到字典中,其中对象是您要执行的函数。

这也将成为自我文档,您也将能够自动创建帮助文档!

如果您愿意,我明天可以快速发布一个示例。 -在下面添加代码示例的关键部分(来自Program.cs文件):

我们将用于捕获REPL命令信息的类:

    class ReplCommand
    {

        public string Command { get; set; }
        public string HelpText { get; set; }
        public Action<string> MethodToCall { get; set; }
        public int HelpSortOrder { get; set; }

    }

这是我们定义所有有效命令的地方

        static void PopulateCommands()
        {
            // Add your commands here
            AddCommand(new ReplCommand
            {
                Command = "MyCommand", // The command that the user will enter (case insensitive)
                HelpText = "This is the help text of my command", // Help text
                MethodToCall = MyCommand, // The actual method that we will trigger
                HelpSortOrder = 1 // The order in which the command will be displayed in the help
            });

            // Default Commands
            AddCommand(new ReplCommand
            {
                Command = "help",
                HelpText = "Prints usage information",
                MethodToCall = PrintHelp,
                HelpSortOrder = 100
            });
            AddCommand(new ReplCommand
            {
                Command = "quit",
                HelpText = "Terminates the console application",
                MethodToCall = Quit,
                HelpSortOrder = 101
            });

        }

        static void AddCommand(ReplCommand replCommand)
        {
            // Add the command into the dictionary to be looked up later
            _commands.Add(replCommand.Command, replCommand);
        }

这是程序的关键部分:

        // The dictionary where we will keep a list of all valid commands
        static Dictionary<string, ReplCommand> _commands = new Dictionary<string, ReplCommand>(StringComparer.CurrentCultureIgnoreCase);

        static void Main(string[] args)
        {
            // Create Commands
            PopulateCommands();

            // Run continuously until "quit" is entered
            while (true)
            {
                // Ask the user to enter their command
                Console.WriteLine("Please input your command and hit enter");
                // Capture the input
                string sInput = Console.ReadLine();
                // Search the input from within the commands
                if (_commands.TryGetValue(sInput, out ReplCommand c))
                {
                    // Found the command. Let's execute it
                    c.MethodToCall(sInput);
                }
                else
                {
                    // Command was not found, trigger the help text
                    PrintHelp(sInput);
                }
            }


        }

上面定义的每个注释的具体实现:

        static void MyCommand(string input)
        {
            Console.WriteLine($"MyCommand has been executed by the input '{input}'");
        }

        static void PrintHelp(string input)
        {
            // Unless the input that got us here is 'help', display the (wrong) command that was
            // entered that got us here
            if (input?.ToLowerInvariant() != "help")
            {
                // Display the wrong command
                Console.WriteLine($"Command '{input}' not recognized. See below for valid commands");
            }

            // Loop through each command from a list sorted by the HelpSortOrder
            foreach (ReplCommand c in _commands.Values.OrderBy(o => o.HelpSortOrder))
            {
                // Print the command and its associated HelpText
                Console.WriteLine($"{c.Command}:\t{c.HelpText}");
            }
        }

        static void Quit(string input)
        {
            System.Environment.Exit(0);
        }

    }

}

这里是指向complete Program.cs file的链接。

我已将完整的代码库上传到我的GitHub Repo中。

答案 1 :(得分:0)

在这种情况下,我通常会尝试调味,直到满意为止

  

我每次要求用户输入然后检查它时重复

然后将其包装在函数/方法中,这样您只需要将其维护在一个地方

private void ProcessInput(string input)
{
    if(string.IsNullOrEmpty(input)) throw new ArgumentException();

    input = input.Trim().ToLower();

    if(input == "exit" || input == "leave")
    {
        Console.Clear();
        ExitProgram.ExitProg();
        calcInput = false;
    }
    else if(input == "back" || input == "menu")
    {
        TxtFun.CTxt("Returning to previous menu.");
        Console.ReadLine();
        Console.Clear();
        calcInput = false;
        calcLoop = false;
    }
    else
    {
        TxtFun.CTxt("Invalid input.");
        Console.ReadLine();
        Console.Clear();

        calcInput = false;
    }    
}

然后重构每个if块...

private void ProcessExitInput(string input)
{
    if(input == "exit" || input == "leave")
    {
        Console.Clear();
        ExitProgram.ExitProg();
        calcInput = false;
    }
}

private void ProcessMenuInput(string input)
{
    if(input == "back" || input == "menu")
    {
        TxtFun.CTxt("Returning to previous menu.");
        Console.ReadLine();
        Console.Clear();
        calcInput = false;
        calcLoop = false;
    }
}

private void ProcessDefaultInput(string input)
{
    if(input != "back" && input != "menu" && input != "exit" && input != "leave")
    {
        TxtFun.CTxt("Returning to previous menu.");
        Console.ReadLine();
        Console.Clear();
        calcInput = false;
        calcLoop = false;
    }
}

现在您的ProcessInput方法变得更小...

private void ProcessInput(string input)
{
    if(string.IsNullOrEmpty(input)) throw new ArgumentException();

    input = input.Trim().ToLower();

    ProcessExitInput(input);
    ProcessMenuInput(input);
    ProcessDefaultInput(input);
}

您甚至可以使用switch / case块代替if / else块。甚至将if条件重构为一个单独的对象...

class InputHandler
{
    public static bool IsExitInput(string input)
    {
        return input == "exit" || input == "leave";
    }
}

您还可以创建一个InputFactory对象,该对象根据特定条件(IInputProcessor)返回特定的input接口实现。像...

public interface IInputProcessor
{
    void Process();
}

public class ExitInputProcessor : IInputProcessor
{

    public void Process()
    {
        //process the exit command input
    }

}

并制作一个InputFactory对象以根据当前输入返回所需的实现

您可以做任何有助于您稍后组织和维护该代码的事情,并且对如何编写代码没有绝对的答案。 一个提示,测试驱动的开发通常有助于编写更清晰和可维护的代码