我的函数有一项工作:返回一个简单的int
索引。但是,为了“计算”该索引,它考虑了一些参数(在我的情况下为3,但为简单起见,在此示例中,我将使用2个参数)。我的函数看起来像这样:
int calculateIndex(int param1, int param2)
现在,它目前是如何工作的?它是在“层”中进行的。首先,它检查什么是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
{
}
}
需要注意的重要一点是,param1
的每种情况都可以有任意数量的if-elses
。例如,如果param2
为0,则param1
可能有3种情况。但是,如果param2
为1,则param1
有2种情况,为param2
或3
。
如果这一切都没有道理,让我给您举一个实际的例子。考虑以下功能:
else
void uselessFunction(int biome, int element)
以uselessFunction
和biome
索引为参数,并根据输入显示适当的消息。
element
现在,该示例相当简短,但是如您所见,只有2个生物群落和几个块,此代码已经相当长。想象一下有20个生物群落的情况,每个生物群落都有10-15个可能出现在其上的方块。这会导致难以置信的长时间执行简单任务的功能,我需要一种更好的方法来设计该功能。怎么样?
答案 0 :(得分:7)
您想要的技术称为“表驱动编程”。您将建立一系列包含您感兴趣的数据的“表”,然后进行表查找,而不是执行if-else系列。
由于您的元素表只是确定-不作决定,因此您甚至不需要字典;只需一组即可:
var biomeTable = new Dictionary<Biome, HashSet<Element>>()
{
{ Forest, new HashSet<Element>() { Grass, Water }},
{ Desert, new HashSet<Element>() { Sand }}
};
现在您的代码是:
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}.");
看看情况如何?逻辑只是两个if-thens,不如生物群系/元素组合那么多。信息进入数据结构,而不进入代码结构。
通过这种方式,您可以将生物群系和元素放入配置文件中,并从文件中解析它们,构建字典并根据需要动态设置。
答案 1 :(得分:2)
您的夫妻在条件字典中使用Tuple作为复合键。
在下面的示例中,每个Dictionary项的值都是一个字符串(如您的示例中,消息是唯一的区别因素)。
但是,它也可以是实现接口的类型或类型实例,例如IBiomeElementLogic,并且每个键都有不同的实现。
这将是Inversion of Control的一种形式。
enum Biome
{
Forest = 1,
Desert = 2
}
enum Element
{
Grass = 1,
Water = 2,
Sand = 3
}
static readonly Dictionary<(Biome, Element), string> Conditions = new Dictionary<(Biome, Element), string>
{
{ (Biome.Forest, Element.Grass) , "There is grass in the forest." },
{ (Biome.Forest, Element.Water) , "There is water in the forest." },
{ (Biome.Desert, Element.Sand) , "There is sand in the desert." }
};
static void Main(string[] args)
{
UselessFunction(Biome.Forest, Element.Grass);
UselessFunction(Biome.Forest, Element.Water);
UselessFunction(Biome.Forest, (Element)100);
UselessFunction(Biome.Desert, Element.Sand);
UselessFunction(Biome.Desert, (Element)100);
UselessFunction((Biome)100, Element.Grass);
Console.Read();
}
static void UselessFunction(Biome biome, Element element)
{
var key = (biome, element);
if (Conditions.ContainsKey(key))
{
Print(Conditions[key]);
}
else if (Enum.IsDefined(typeof(Biome), biome))
{
Print("Given element is invalid for this biome.");
}
else
{
Print("Given biome is invalid.");
}
}
static void Print(string message)
{
Console.WriteLine(message);
}
答案 2 :(得分:-1)
这项技术将帮助您简化方法中的逻辑。
class BiomeElement
{
public BiomeElement(int biome, int element)
{
Biome = biome;
Element = element;
}
public int Biome { get; }
public int Element { get; }
public bool IsForestGrass { get { return Biome == 1 && Element == 1; } }
public bool IsForestWater { get { return Biome == 1 && Element == 2; } }
}