1

我正在构建一个控制台应用程序来帮助加快我经常做的一些事情。我有一个包含 4 个程序选项的菜单,它们可以转化为我课堂上的不同方法。

基本上是这样的:

你想让我做什么?

1 这东西

2 那件事

3 一些东西

4 很酷的东西

0 所有的东西。

输入命令字符串:_

目前我正在检查有效输入:

while (command.IndexOfAny("12340".ToCharArray()) == -1)
{
  //Display the menu and accept input
}

然后通过以下方式控制流量:

if (command.IndexOf("1") > 0 )
{
  thisThing();
}

if (command.IndexOf("2") > 0 )
{
  thatThing();
}

if (command.IndexOf("3") > 0 )
{
  someStuff();
}

if (command.IndexOf("4") > 0 )
{
  coolStuff();
}

if (command.IndexOf("0") > 0 )
{
  thisThing();
  thatThing();
  someStuff();
  coolStuff();
}

目标是提供输入并运行一个或多个进程,如下所示:

1:这件事()

13 : thisThing() 和 someStuff();

42 : thatThing() 和coolStuff();

0:运行我定义的所有进程。

有没有办法通过更好的做法来做这样的事情?

4

4 回答 4

2

我会创建一个Dictionary<char, DoSomething>

public delegate void DoSomething();

Dictionary<char, DoSomething> commands = new Dictionary<char, DoThing>();
commands.Add('0', new DoSomething(DoAll));
commands.Add('1', new DoSomething(ThisThing));
commands.Add('2', new DoSomething(ThatThing));
commands.Add('3', new DoSomething(SomeStuff));
commands.Add('4', new DoSomething(CoolStuff));

然后,在输入验证之后

foreach(char c in command.ToCharArray()) 
{  
   // Better check if the input is valid
   if(commands.ContainsKey(c))
       commands[c].Invoke();
}

Dictionary 包含,作为键,允许的字符,作为值,包含返回 void 且没有参数的函数的委托。现在只需按字符循环输入字符并调用相关方法即可。

保持现状,这种方法很少有选择,并不比简单的if/else if/elseswitch/case更好。同样通过这种方式,您的用户可以键入2442反转方法的执行顺序,这在您的真实上下文中是不允许的。

于 2014-09-11T15:10:05.720 回答
1

我会创建一个代表字典。字典键将是输入值,委托将执行代码。

此处介绍了语法C# Store functions in a Dictionary

这样,您可以循环输入字符串并进行字典查找;如果值存在则执行委托,否则跳过。

它并不比 if else if endif set 特别好,尽管我发现它更具吸引力和可扩展性。

于 2014-09-11T15:07:59.913 回答
1

我在Ayende Rahien 项目中基于正则表达式找到了一种非常好的方法,他在其中解析Freedb.org数据文件的内容

基本上,解析器设置了一个列表,Tuple<Regex, Action<contextual class>>其中上下文类根据解析器当时所在的位置而变化。然后解析变成尝试将每个元素(在本例中为行)与正则表达式匹配,并在匹配时执行相应的操作。

在您的情况下,您可以将您的命令链接到多个输入,例如

public class Parser
{
    readonly List<Tuple<Regex, Action>> actions = new List<Tuple<Regex, Action>>();
    public Parser()
    {
        Add(@"^0$", () => { DoSomething(); });
        Add(@"^DoSomething$", () => { DoSomething(); });

        Add(@"^1$", () => { DoSomethingElse() });
        Add(@"^DoSomethingElse$", () => { DoSomethingElse() });

        // etc
    }
    private void Add(string regex, Action action)
    {
        var key = new Regex(regex, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
        actions.Add(Tuple.Create(key, action));
    }

    public void Parse(string text)
    {
        foreach (var action in actions)
        {
            var collection = action.Item1.Matches(text);
            try
            {
                action.Item2();
            }
            catch (Exception e)
            {
                // log?
                throw;
            }
        }
    }
}

它使您可以使用不同的输入运行所需的方法。

于 2014-09-11T16:13:23.987 回答
0

我会创建一个接口,所有命令都从该接口派生,并有一个 switch 语句确定要执行的操作。类似于...的东西

public abstract class ISystem
{
    public abstract void DoSomething();
}

public class ThisThing : ISystem
{
    public override void DoSomething()
    {
        Console.WriteLine("Do This Thing");
    }
}

public class ThatThing : ISystem
{
    public override void DoSomething()
    {
        Console.WriteLine("Do That Thing");
    }
}

static void Main(string[] args)
{
    var input = "-1";
    while(/*input is invalid*/)
    {
        // get input from user
    }

    var thisThing = new ThisThing();
    var thatThing = new ThatThing();

    switch(input)
    {
        case "1":
           {
               thisThing.DoSomething();
               break;
           }
        case "2":
           {
               thatThing.DoSomething();
               break;
           }
        case "0":
           {
               var commands = new List<ISystem>();
               commands.Add(thisThing);
               commands.Add(thatThing);

               // Execute all commands
               commands.ForEach(system => system.DoSomething());
               break;
           }
    }
}

这里的好处是每次添加新命令时只需要实现DoSomething()方法,之后创建类的实例var someStuff = new SomeStuff();然后添加到命令列表中的简单任务case "0":

另外,IMO 的意图比管理字典等更清晰。

于 2014-09-11T15:41:39.807 回答