我的任务是编写一个程序,该程序向用户提供带有4个选项的菜单,然后接受输入并使用输入进行一些计算。最好的方法是什么?
作为参考,我的方法是使用所有菜单选项制作一个enum
,并使其控制switch
语句来控制操作。
private enum MainMenu
{
CYLINDER = 1,
CUBE,
SPHERE,
QUIT,
UNASSIGNED
}
MainMenu mmChoice = MainMenu.UNASSIGNED;
string sInput = Console.ReadLine();
switch (mmChoice)
{
case MainMenu.CYLINDER:
doWork1();
break;
case MainMenu.CUBE:
doWork2();
break;
case MainMenu.SPHERE:
doWork3();
break;
case MainMenu.QUIT:
Exit();
break;
case MainMenu.UNASSIGNED:
break;
}
案例中发生的事情并不重要,但我想知道如何从句法上进行这项工作。由于我使用的是来自用户的输入(由Console.ReadLine()
获取,该输入返回了string
,并且我需要以enum
的形式输入),所以我不知道该如何进行。如何将sInput与mmChoice相关联并操作开关?
我知道这是在问两个问题,但是出于任务的目的,我希望有人回答具体情况,也许有人可以在评论中告诉我最好的一般方法。
答案 0 :(得分:0)
在注释中已经指出: 您要做的就是分别使用TryParse / Parse将输入转换为枚举
请注意,建议在处理用户输入时使用TryParse(或者几乎在您无法保证解析将起作用的任何其他时间)。
MainMenu mmChoice = MainMenu.UNASSIGNED;
Console.WriteLine("?");
string sInput = Console.ReadLine();
if(Enum.TryParse(sInput, out mmChoice))
{
switch(mmChoice)
{
case MainMenu.CYLINDER:
Console.WriteLine("cylinder");
break;
case MainMenu.CUBE:
Console.WriteLine("cube");
break;
case MainMenu.SPHERE:
Console.WriteLine("sphere");
break;
case MainMenu.QUIT:
Console.WriteLine("quit");
break;
case MainMenu.UNASSIGNED:
break;
}
}
EDIT : 由于OP在评论中要求使用基于字符的解决方案:
Console.WriteLine("?");
char sInput = Console.ReadKey().KeyChar;
Console.WriteLine("");
switch (sInput)
{
case 'a':
Console.WriteLine("cylinder");
break;
case 'b':
Console.WriteLine("cube");
break;
case 'c':
Console.WriteLine("sphere");
break;
case 'd':
Console.WriteLine("quit");
break;
default :
break; // error handling here
}
答案 1 :(得分:0)
仅仅是有趣的,面向对象的方法
public interface IJob
{
void Do();
}
public class JobOne : IJob
{
public void Do()
{
// do something
}
}
public class JobTwo : IJob
{
public void Do()
{
// do something different
}
}
public class DoNothing : IJob
{
public void Do() { }
}
public class JobRunner
{
private readonly Dictionary<string IJob> _jobs;
private readonly IJob _doNothing;
public JobRunner()
{
_jobs = new Dictionary<string, IJob>
{
{ "one", new JobOne() },
{ "two", new JobTwo() },
};
_doNothing = new DoNothing();
}
public void Run(string jobKey)
{
_jobs.GetValueOrDefault(jobkey, _doNothing).Do();
}
}
用法如下:
vr runner = new JobRunner();
var input = Console.ReadLine();
runner.Run(input);
答案 2 :(得分:0)
这是另一种方法,该方法是创建一个表示MenuItem
的类,该类具有说明和相关的方法(如果选择了该项目,则应调用该方法)。
private class MenuItem
{
public string Description { get; set; }
public Action Execute { get; set; }
}
然后,我们可以填充这些项目的列表,以显示在MainMenu
// Our private list of menu items that will be displayed to the user
private static List<MenuItem> MenuItems;
// A helper method to populate our list.
// We can easily add or remove new items to the menu
// without having to worry about changing an
// enum or adding a command to a switch block
private static void PopulateMenuItems()
{
MenuItems = new List<MenuItem>
{
new MenuItem {Description = "View balance", Execute = ViewBalance},
new MenuItem {Description = "Deposit", Execute = Deposit},
new MenuItem {Description = "Withdraw", Execute = Withdraw},
};
}
请注意,每个项目都具有Execute
类型的Action
属性,并且在上面为其分配了值。这些值实际上是可以在项目中其他位置定义的方法。当前,每个方法只是一个存根,它调用一个帮助程序方法以显示标题,另一个调用帮助程序方法以提示用户返回主菜单,但是它们可能包含实际功能:
private static void ViewBalance()
{
ClearAndShowHeading("Account Balance");
GoToMainMenu();
}
private static void Deposit()
{
ClearAndShowHeading("Account Deposit");
GoToMainMenu();
}
private static void Withdraw()
{
ClearAndShowHeading("Account Withdrawl");
GoToMainMenu();
}
private static void ClearAndShowHeading(string heading)
{
Console.Clear();
Console.WriteLine(heading);
Console.WriteLine(new string('-', heading?.Length ?? 0));
}
private static void GoToMainMenu()
{
Console.Write("\nPress any key to go to the main menu...");
Console.ReadKey();
MainMenu();
}
因此,既然我们有了菜单项的列表,我们就可以创建一个方法来显示它们,这也将获得用户选择的菜单项的输入,然后调用关联的方法(通过{{1} }属性。
请注意,此处还进行了一些验证,以确保用户仅选择有效的项目。我们根据列表中的索引显示项目(将索引添加到索引中,这样列表就不会以Execute
开头),然后将用户输入传递给0.
方法。此方法将尝试将用户的输入解析为整数。如果解析成功,则该方法返回int.TryParse
(并且退出循环),并且true
参数将包含该值。
这是在循环内完成的,因此,如果用户输入了无效的数字,则我们将光标设置回该行的开头,在其上写空格,然后再次将光标设置回该行的开头,提示他们输入:
out
现在,通过这种方式,自定义菜单项,向用户显示菜单项并相应地执行正确的方法非常容易:
static void MainMenu()
{
ClearAndShowHeading("Main Menu");
// Write out the menu options
for (int i = 0; i < MenuItems.Count; i++)
{
Console.WriteLine($" {i + 1}. {MenuItems[i].Description}");
}
// Get the cursor position for later use
// (to clear the line if they enter invalid input)
int cursorTop = Console.CursorTop + 1;
int userInput;
// Get the user input
do
{
// These three lines clear the previous input so we can re-display the prompt
Console.SetCursorPosition(0, cursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, cursorTop);
Console.Write($"Enter a choice (1 - {MenuItems.Count}): ");
} while (!int.TryParse(Console.ReadLine(), out userInput) ||
userInput < 1 || userInput > MenuItems.Count);
// Execute the menu item function
MenuItems[userInput - 1].Execute();
}
尝试一下,看看您的想法。菜单将如下所示:
现在,如果我们要添加新的菜单项怎么办?简单!在代码块中添加以下行,我们在static void Main(string[] args)
{
PopulateMenuItems();
MainMenu();
Console.Write("\nDone! Press any key to exit...");
Console.ReadKey();
}
方法内将项目分配给MenuItems
,然后再次运行它:
PopulateMenuItems
现在我们的菜单如下: