什么是大型开关盒的好替代品?

Posted

技术标签:

【中文标题】什么是大型开关盒的好替代品?【英文标题】:What is a good substitute for a big switch-case? 【发布时间】:2015-02-16 04:55:32 【问题描述】:

我有名为 Country 的对象。在程序中的某个时刻,我想设置每个对象的场功率。

每个国家/地区的功率是固定的,我在一张纸上记录了所有 196 个国家/地区的数据。例如,我的代码应该检查该国家/地区的名称是否为 USA(如果是,请将其幂设置为 100)等等。

我知道我可以使用 switch-case 来做到这一点,但是最好、最好和最有效的方法是什么?

【问题讨论】:

使用Dictionary<country,power> 作为查找表。 我认为 switch 语句不会那么大。 switch (country) case "USA": return 100; default: return 0; fubo: 很抱歉吹毛求疵,但你误会国家和州了。国家是地理单位,没有权力......更重要的是,请注意,由于您有很多国家,子类化(即由其他类继承 Country)不是一种选择。但是,如果您只有几个可能的值,则可以有 Country::Weak 类、Country::Medium 类、Country::Strong 类,每个都有自己的恒定功率值。 感谢您的评论 :) 在我的代码中他们被称为玩家,我在这里写了国家,以便阅读的人能更好地理解! 你可以试一试。 【参考方案1】:

您可以将国家/地区力量对存储到Dictionary<string, int> 中,然后使用索引器获取特定国家/地区的分数:

var points = new Dictionary<string,int>();
// populate the dictionary...
var usa = points["USA"];

编辑: 正如 cmets 中所建议的,您应该将信息存储在外部文件中,例如 xml 将是一个不错的选择。这样您就不必修改代码来添加或删除国家/地区。您只需要将它们存储到 XML 文件中,在需要时进行编辑。然后在程序启动时对其进行解析,并将值加载到 Dictionary。您可以使用 LINQ to XML。如果您以前没有使用过documentation 中有很好的示例可以帮助您入门。

【讨论】:

我建议将数据存储在文件或数据库中,即不在代码中! 196 个数据集的数量绝对不适合硬编码。 补充一下@ComFreek 所说的,JSON 将非常适合,并且是一种很好的可移植格式,具有轻松解析成字典的现有方法。 读取文件的一种非常简单的方法是:var dict = System.IO.File.ReadLines(@"C:\path\file.extension").Select(line =&gt; line.Split(',')).ToDictionary(arr =&gt; arr[0], arr =&gt; int.Parse(arr[1]));,它假定它是逗号分隔的文本格式(如 .csv 文件),没有空行。当然,在很多情况下都可能出现例外情况。如果需要更健壮,请务必选择问题最后一节中建议的 XML 方案。 致崇尚外部文件的人们:KISS,YAGNI! OP告诉我们“每个国家的力量都是固定的”。硬编码是一个很好的解决方案,如果需要,可以很容易地对其进行改进。当然,需求可能会改变,但可能不会。查看管理外部资源的额外复杂性:文件丢失、编码错误、损坏;现在处理异常,记录错误,通知用户。此外,一个简单的开关就足够了:编译器无论如何都会生成一个字典(见我的回答)。 @coredump 并添加了一条进一步的评论,指出“在我的代码中,他们被称为玩家,我在这里写了国家,以便阅读的人能更好地理解”,所以不能保证它会被修复到 196 - 根据大多数统计,有 209 个国家,或 193 个联合国会员国,2 个观察员和 11 个“其他”【参考方案2】:

虽然 Selmans 的回答是正确和好的,但它并没有回答如何实际填充字典。就是这样:

var map = new Dictionary<string, int> 
    "USA", 100,
    "Germany", 110
;

不过,您也可以按如下方式添加:

map.Add("USA", 100);
map.Add("Germany", 110);

现在您可以访问该值(正如 Semans 已经提到的):

map["USA"] = 50;        // set new value for USA
int power = map["USA"]; // get new value

编辑:正如在 cmets 和其他答案中已经提到的,您当然可以将数据存储在外部文件或任何其他数据存储中。话虽如此,您可能只是初始化一个空字典,然后使用前面提到的针对该存储中的每条记录的 Add-method 填充它。

【讨论】:

+1 很好的例子,因为我喜欢它显示给nasim 如何加载/填充/访问字典 对象 如果此列表发生更改并且您希望在不占用开发人员时间的情况下对其进行维护,您应该从易于编辑的配置文件中加载这些值。 我可能会在一个使用 GridView 的简单配置菜单中编写代码,这样用户就可以在程序中而不是记事本中进行更改。 @Cory - 配置文件可能很棒,所以我并不完全不同意你的观点,但我忍不住指出相反的可能性:如果列表不太可能经常更改,它可能会占用开发人员更多的时间来决定文件格式、编写代码来解析文件、处理“找不到文件”或解析错误、修复错误……:-) @antinome - 这是一个有效的观点,但我还没有遇到一种编程语言,它最多只能在几行内从 JSON 文件构建字典。【参考方案3】:

这是一个正确的问题,但是你需要学习很多东西。许多人已经回答了你提出的问题。我要烦禅了,告诉你不要问这个问题,因为有一个更大的问题要解决。

与其硬编码,不如将相关属性存储在一个 n 元组(也称为数据库行)中,并使用数据库引擎来管理两者之间的关系。然后,由于您使用的是 C#,因此学习使用 LINQ 可能会很聪明。但在你这样做之前,先学习一点数据建模理论,因为数据建模就是你正在做的事情。

【讨论】:

“当你唯一的工具是锤子时,一切看起来都像钉子。”对于这个问题,引入数据库似乎是严重的矫枉过正。但我同意建议从文件加载数据而不是硬编码的答案。 哇!!感谢大家提供所有这些解决方案。我肯定有很多东西要学!直到一个月前,我唯一的工具是数组,所以字典对我来说是一个升级!! :D 但是我学得很快,谢谢你们 我会删除关于“以上”答案的讨论。答案可以以多种方式排序。相反,只需说出您的实际意思。 “从长远来看,告诉您如何对国家/地区进行硬编码的答案对您没有任何好处。” @MiniRagnarok 我同意,但我要说明两点。一个是建筑学的,另一个是关于深层次与浅层次的教学。我会稍微改写一下。 @IanGoldby - 正确的工具是 TCO 最低的工具。数据库的编写成本、调试成本、维护成本和数据操作成本都较低,因为结构化数据操作是一个已解决的问题。停止重新发明***。【参考方案4】:

由于您说您有名为“Country”的“对象”,并且您已将问题标记为“C#”,因此您的代码中似乎有两种力量在起作用。一个是必须引用一个映射,无论多么有效地实现,并不像引用一个成员变量那么便宜。另一方面,如果一个国家的所有属性都可以在与其他国家的属性相同的位置找到,则可能会有一些好处(面向地图的解决方案确实解决了这个问题)。但是这些力量可以像这样调和:

class Country  // Apologies that this sketch is more C++ than C#
public:
   Country(string name_, int power_);
private:
   string name;
   int power;
;
void MakeCountries()

    countries.Add(new Country("USA", 50));
    countries.Add(new Country("Germany", 60));
    // ....

【讨论】:

【参考方案5】:

您需要在运行时更新数据吗?

是吗?将数据从外部存储加载到字典中。

否? 使用开关

让编译器为您生成字典和基于哈希的查找。 当您的分析器开始尖叫时,请探索替代解决方案。 例如,从“What is quicker, switch on string or elseif on type?”读取that answer。

【讨论】:

对于“是吗?”问题我同意你的回答,因为“不?使用开关”不是。 196 个国家/地区的 switch 语句(Nasim 提到了数据量)在我看来不是一个好习惯。【参考方案6】:

如果创建一个字符串数组来存储国家/地区名称,按其权力的升序排列。实施起来会更简单。然后每个国家的指数就可以代表它的实力。这是可能的,只有当电源继续计数时。

如果不是,另一种简单的方法是将它们实现为链表。这样您就可以根据需要进行更改。包含 2 个字段的列表; 1为国,为权

【讨论】:

以上是关于什么是大型开关盒的好替代品?的主要内容,如果未能解决你的问题,请参考以下文章

corba的好替代品[关闭]

对于相对较新的计算机,啥是 ol' C++ Beep() 的好替代品?

Web 浏览器组件的好替代品?

开关盒的样式

带有开关盒的 JOptionPane

asp.net ajax 4.0 模板的替代品