在尝试查找由多个参数确定的值时,如何避免巨大的if-else检查?

FIC*_*EKK 1 c# refactoring

我的函数有1个工作:返回一个简单的int索引.但是,为了"计算"该索引,它考虑了一些参数(在我的情况下为3,但为了简单起见,我将在此示例中使用2个参数).我的函数看起来像这样:

int calculateIndex(int param1, int param2)
Run Code Online (Sandbox Code Playgroud)

现在,它目前是如何完成这项工作的?它在"层"中这样做.首先,它检查什么是价值param1.一旦建立了它,它就会开始检查是什么值param2,依此类推.像这样:

if(param1 == 0)
{
    if(param2 == 0)
    {
        // Return some value.
    }
    else if(param2 == 1)
    {

    }
    else
    {

    }
}
else if(param1 == 1)
{
    if(param2 == 3)
    {

    }
    else
    {

    }
}
else
{
    if(param2 == 4)
    {

    }
    else if(param2 == 5)
    {

    }
    else if(param2 == 6)
    {

    }
    else if(param2 == 7)
    {

    }
    else
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

需要注意的是,每个案例都param1可以有任意数量的if-elsesfor param2.例如,如果param1为0,则可能有3种情况param2.但是,如果param1是1,param2有2个案例,则是3或者else.

如果这些都没有意义,那么让我举一个实际的例子.考虑以下功能:

void uselessFunction(int biome, int element)
Run Code Online (Sandbox Code Playgroud)

uselessFunctionbiomeelement索引作为基于输入参数和打印相应的消息.

// Forest, Grass etc. are integer constants.

if(biome == Forest)
{
    if(element == Grass)
    {
        print("There is grass in the forest.");
    }
    else if(element == Water)
    {
        print("There is water in the forest.");
    }
    else
    {
        print("Given element is invalid for this biome.");
    }
}
else if(biome == Desert)
{
    if(element == Sand)
    {
        print("There is sand in the desert.");
    }
    else
    {
        print("Given element is invalid for this biome.");
    }
}
else
{
    print("Given biome is invalid.");
}
Run Code Online (Sandbox Code Playgroud)

现在,这个例子相当简短,但正如你所看到的,只有2个生物群系和几个块,这个代码已经很久了.想象一下20个生物群系的情况,每个生物群系都有10-15个块可以出现在它们身上.这会导致执行简单任务的令人难以置信的长功能,我需要一种更好的方法来设计该功能.怎么样?

Eri*_*ert 7

您想要的技术称为"表驱动编程".您建立了一系列包含您感兴趣的数据的"表",然后执行表查找,而不是执行if-else系列.

由于你的元素表只是肯定 - 没有决定,你甚至不需要字典; 只需一套即可:

var biomeTable = new Dictionary<Biome, HashSet<Element>>()
{
  { Forest, new HashSet<Element>() { Grass, Water }},
  { Desert, new HashSet<Element>() { Sand }}
};
Run Code Online (Sandbox Code Playgroud)

现在你的代码是:

if (biomeTable.ContainsKey(biome)) 
{
  if (biomeTable[biome].Contains(element))
    Console.WriteLine($"The {biome} contains {element}.");
  else
    Console.WriteLine($"The {biome} does not contain {element}.");
} 
else
   Console.WriteLine($"Invalid biome {biome}.");
Run Code Online (Sandbox Code Playgroud)

看看怎么样?逻辑只是两个if-thens,没有生物群落/元素组合那么多.信息在数据结构中,而不是在代码的结构中.

这样,您可以将生物群系和元素放入配置文件中,并将其解析出文件,构建字典并根据需要动态设置.