【问题标题】:Is there Any Way to Simplify this Function?有没有办法简化这个功能?
【发布时间】:2021-06-22 11:10:48
【问题描述】:

我有一个函数,它返回一个字符串,其中包含对象正在查看的坐标和方向。 但我真的不喜欢函数的长度,我想缩短它。我不知道我能做些什么来缩短它。有人可以帮我吗?

函数如下所示:

public string Execute(string text)
{
    var letters = text.ToCharArray().ToList();

    foreach (var letter in letters)
    {
        if (letter == 'R')
        {
            switch(direction)
            {
                case "N":
                    direction = "E";
                    break;
                case "E":
                    direction = "S";
                    break;
                case "S":
                    direction = "W";
                    break;
                case "W":
                    direction = "N";
                    break;
            }
        }

        if (letter == 'L')
        {
            switch (direction)
            {
                case "N":
                    direction = "W";
                    break;
                case "E":
                    direction = "N";
                    break;
                case "S":
                    direction = "E";
                    break;
                case "W":
                    direction = "S";
                    break;
            }
        }

        if (letter == 'M')
        {
            switch (direction)
            {
                case "N":
                    positionY++;
                    break;
                case "E":
                    positionX++;
                    break;
                case "S":
                    positionY--;
                    break;
                case "W":
                    positionX--;
                    break;
            }
        }
            
        if (letter == 'B')
        {
            switch (direction)
            {
                case "N":
                    positionY--;
                    break;
                case "E":
                    positionX--;
                    break;
                case "S":
                    positionY++;
                    break;
                case "W":
                    positionX++;
                    break;
            }
        }
    }

    return $"{positionX}:{positionY}:{direction}";
}

This Text Down here 只是一个无用的文本,所以我可以提交我的问题,因为我的代码太长并且 Stackoverflow 将问题识别为主要是代码,所以我必须编写更多没有代码括号的文本才能提交问题.您不必阅读此文本,因为它没有任何目的。

【问题讨论】:

  • 寻找模式,并想办法在算法中使用它们。例如,对于RL,看起来直接顺时针或逆时针旋转。您可以编写一个小函数来启用它(使用方向字符串数组(您可以环绕)并且您的代码在数组中向左或向右移动)。同样,对于MB,您以固定模式将位置偏移+1-1。将该逻辑重构为一个能够计算出规则的函数。
  • 使用以旧值作为键,以新值作为值的字典。 Dictionary lDict = new Dictionary() { { "N", "W" }, { "E", "N" }, { "S", "E" }, { " W", "S" } }; dict = lDict[dict];
  • 在我看来,这正是正确的做法。尽管这可能是“智能”解决方案的更多代码行,但它是最容易维护和理解的。到目前为止,对于此处提出的所有其他解决方案,如果您或其他人以后必须更改它,您将很难过。相反,每个人都会立即理解简单的“切换”方法。

标签: c# refactoring simplify


【解决方案1】:

我意识到 OP 可能不再对这个问题的答案感兴趣,但我还是会分享我的想法。

Switch expressions 是在 C# 8.0 中引入的,它们可用于简化/缩短(部分)代码。

函数的前两个if 循环中的switch 语句可以直接替换为switch 表达式。第一个if 循环中switch 语句的替换如下:

if (letter == 'R')
{   
    direction = direction switch
    {
        "N" => "E", // interpretation: if the current direction is "N", assign "E"
        "E" => "S",
        "S" => "W",
        "W" => "N",
        _ => direction // discard pattern to provide a default value in case there is no match
    };
}

第二个if 循环中的switch 语句可以用类似的方式替换。


为了进一步缩短您的代码,您可以考虑在您的 switch 表达式中包含 case guards

但是:在引入大小写保护时,阅读和解释switch 表达式通常需要更多的努力。正如上面的@Heinz Kessler cmets,为了减少代码行而进行的“智能”编码不值得牺牲代码的可读性和可维护性。

如果有兴趣/好奇,here is a working DotNetFiddle example 了解您的代码可以如何使用 switch 表达式和案例保护来实现。为此,我更改了Execute 方法中的逻辑。为了可读性(这可能是个人喜好),还进行了变量重命名和引入常量等更改。

【讨论】:

    【解决方案2】:

    尝试以下:

               string text = "";
                var letters = text.ToCharArray().ToList();
                Dictionary<char, Dictionary<string, string>> dict = new Dictionary<char, Dictionary<string, string>>() {
                    {'R', new Dictionary<string, string>() { { "N", "E" }, { "E", "S" }, { "S", "W" }, { "W", "N" }}},
                    {'L', new Dictionary<string, string>() { { "N", "W" }, { "E", "N" }, { "S", "E" }, { "W", "S" }}},
                    {'M', new Dictionary<string, string>() { { "N", "AY" }, { "E", "AX" }, { "S", "SY" }, { "W", "SX" }}},
                    {'R', new Dictionary<string, string>() { { "N", "SY" }, { "E", "SX" }, { "N", "AY" }, { "N", "AX" }}}
                };
                string direction = "";
                int positionX = 0;
                int positionY = 0;
    
                foreach (var letter in letters)
                {
                    string value = dict[letter][direction];
                    switch (value)
                    {
                        case "SX":
                            positionX--;
                            break;
                        case "SY":
                            positionY--;
                            break;
                        case "AX":
                            positionX++;
                            break;
                        case "AY":
                            positionY++;
                            break;
                        case "N":
                            direction = value;
                            break;
                        case "E":
                            direction = value;
                            break;
                        case "S":
                            direction = value;
                            break;
                        case "W":
                            direction = value;
                            break;
                    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      • 2011-10-12
      相关资源
      最近更新 更多