繁体   English   中英

如何重构这些 switch case 以处理用户在自然语言中的选择?

[英]How to refactor these switch cases to handle user choice in natural language?

我正在写几个嵌套的 switch 语句,在某些地方有很多情况。

我试图找出一种方法来创建一个案例列表,然后在以后的 switch 语句中引用。

有没有办法做到这一点?

它肯定会清理我的代码。

例如,对于“是”的回答,我有四个不同的案例。

我正在寻找一种方法将这四种情况存储在一个变量中,并在每次我想在开关中使用它们时调用该变量。

Console.Write("\nWere you feeling exhausted? ");
response = Console.ReadLine().ToLower();
Console.Clear();
switch (response)
{
    case "yes":
    case "y":
    case "yep":
    case "yeah":
        {
            goto ThreeTwo;
        }
    case "no":
    case "n":
    case "nope":
    case "nah":

一种简洁明了的方法是首先声明一个enum来表示答案值。 它将需要“是”、“否”“未定义”(后者表示既不是“是”也不是“否”的答案):

public enum YesOrNo
{
    Undefined,
    Yes,
    No
}

然后您可以将是/否检测逻辑包装在 class 中。有很多方法可以做到这一点; 这是一个简单的方法(您可以改用字典,但是对于如此少量的字符串,它并不是真正必要的,我试图使它尽可能简单):

public static class YesOrNoDetector
{
    static readonly string[] _yesAnswers = { "yes", "y", "yep", "yeah", "affirmative" };
    static readonly string[] _noAnswers  = { "no",  "n", "nah", "nope", "negative"    };

    public static YesOrNo Detect(string answer)
    {
        if (_yesAnswers.Contains(answer.ToLower()))
            return YesOrNo.Yes;

        if (_noAnswers.Contains(answer.ToLower()))
            return YesOrNo.No;

        return YesOrNo.Undefined;
    }
}

(请注意它如何通过在比较之前将字符串转换为小写来处理大写答案。)

然后你的原始代码变成这样:

switch (YesOrNoDetector.Detect(response))
{
    case YesOrNo.Yes:
    {
        goto ThreeTwo;  // Please get rid of this goto!
    }

    case YesOrNo.No:
    {
        // Handle "No".
        break;
    }

    case YesOrNo.Undefined:
    {
        // Handle incorrect answer.
        break;
    }
}

有这个枚举:

public enum Answers
{
  Other,
  Yes,
  No
}

可以添加任何预期的可能性。

还可以为各种用例创建多个枚举。

此处Other表示未定义、未预测、未知等。

我们可以定义这个分配/分配/调度表:

using System;
using System.Collections.Generic;

readonly Dictionary<Answers, List<string>> AcceptedAnswers
  = new Dictionary<Answers, List<string>>
  {
    { Answers.Yes, new List<string> { "yes", "y", "yep", "yeah" } },
    { Answers.No, new List<string> { "no", "n", "nope", "nah" } }
  };

因此我们可以轻松地为每个枚举值定义同义词。

我们将通过定义此验证方法来使用它:

Answers GetAnswer(string input)
{
  foreach ( Answers item in Enum.GetValues(typeof(Answers)) )
    if ( AcceptedAnswers.ContainsKey(item) )
      if ( AcceptedAnswers[item].Contains(input) )
        return item;
  return Answers.Other;
}

测试

Console.WriteLine("Do you agree?");
var answer = GetAnswer(Console.ReadLine());
Console.WriteLine();
Console.WriteLine($"Your answer is: {answer}.");

Output

Do you agree?
yep

Your answer is: Yes.

高级用法

bool retry;
do
{
  retry = false;
  Console.WriteLine("Do you agree?");
  var answer = GetAnswer(Console.ReadLine());
  Console.WriteLine();
  Console.WriteLine($"Your answer is: {answer}.");
  switch ( answer )
  {
    case Answers.Yes:
      // ...
      break;
    case Answers.No:
      // ...
      break;
    default:
      Console.WriteLine();
      Console.WriteLine("I don't understand :(");
      Console.WriteLine();
      retry = true;
      break;
  }
}
while ( retry );
Do you agree?
I don't know

Your answer is: Other.

I don't understand :(

Do you agree?
yeah

Your answer is: Yes.

每个世纪请不要多次使用 goto。

使用 goto 时如何解决编译错误“Using unassigned local variable 'hak'”?

暂无
暂无

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

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