方法

2009-10-24 108 views
4

有时候我写在C#3.5丑陋的if-else语句;我意识到使用表驱动开发,类层次结构,一致性方法等等来简化这些方法的不同方法。 问题是替代品仍然较少广泛传播比传统的书写丑陋的if-else语句,因为没有约定这一点。方法

什么深度嵌套的if-else是正常的C#3.5?你期望看到什么方法而不是嵌套if-else第一个?第二?

如果我有在每3个国家中选出十个输入参数,我应该函数映射到每个参数的每个状态的组合(真少,因为并不是所有的国家都有效,但有时还是很多)。我可以将这些状态表示为散列表键和处理程序(lambda),如果键匹配,将会调用它。

它仍然是混合表驱动,数据驱动的开发的。想法和模式匹配。

我正在寻找的是延长C#这样的方法,因为这对脚本(C#3.5,而不是像脚本) http://blogs.msdn.com/ericlippert/archive/2004/02/24/79292.aspx

+1

也许你应该提供一个你的意思的代码样本。我不能想到很多情况下我使用if/else链,除非它们有意义。任何其他时间,我将它们分解成易于理解的代码(将其分解为函数或单独的类)都很困难。 – snarf 2009-10-24 18:49:39

回答

4

有很老的“形式主义”的努力封装极为复杂的表达式计算结果可能许多独立变量,例如,“决策表”:

http://en.wikipedia.org/wiki/Decision_table

不过,我会加入在如果可能的话,合唱团在此再次提及明智地使用三元运算符的想法,找出最不可能的条件,如果符合,允许您通过首先排除它们来终止其余的评估,并添加...相反。 。试图分析出最可能的条件和状态,可以让你在没有测试“边缘”情况下继续进行。

Miriam(上图)的建议引人入胜,甚至是高雅的概念艺术;我实际上会试用它,试图“支持”我怀疑它会导致难以维护的代码。

我的务实一面说,没有一个非常具体的代码示例,没有“一刀切”的答案,并且完整地描述了条件及其相互作用。我设置了一个布尔标志(对于这个类甚至可能是静态的):对于我来说,这个标志可以是任何时候我的应用程序进入一些不太常见的“模式”或“状态”简化了以后编写复杂的if/then评估。

最好,比尔

4

简单。采取if的主体,并从中做出一个方法。

这工作,因为大多数的if语句的形式为:

if (condition): 
    action() 

在其他情况下,更具体:

if (condition1): 
    if (condition2): 
     action() 

简化为:

if (condition1 && condition2): 
    action() 
+1

这仍然难以阅读和理解,特别是如果条件不简单和有些案例分裂,但有些是统一的,有些是默认的。 – rudnev 2009-10-24 16:33:12

+0

如果条件不简单,它们应该在一个单独的函数中进行计算,并且结果应该用在if语句中。 – 2010-10-05 12:50:20

+0

这也不能通过代码覆盖。它会给你一个“部分覆盖”的代码覆盖。 – 2011-12-21 17:31:50

2

我是被很多人忽视的三元运算符的大粉丝。根据条件将值分配给变量是非常好的。像这样

foobarString = (foo == bar) ? "foo equals bar" : "foo does not equal bar"; 

尝试this article了解更多信息。

它不会解决所有的问题,但它是非常经济的。

+0

我爱嵌套的三元运算符。但我问了更复杂的东西:) – rudnev 2009-10-24 16:52:03

1

如果整个目的是根据各种条件的状态为某个变量赋予不同的值,我使用ternery操作符。

如果If Else子句正在执行单独的功能块。并且条件很复杂,通过创建临时布尔变量来保存复杂布尔表达式的真/假值来简化。这些变量应适当命名以表示复杂表达式计算的商业意义。然后使用If else synatx中的布尔变量而不是复杂的布尔表达式。

1

我发现自己有时做的一件事情是将条件逆转为return;在连续几个这样的测试可以帮助减少ifelse嵌套。

0

尝试使用类似的策略或命令

2

我知道,这是不是你正在寻找的答案模式,但没有上下文你的问题是很难回答的问题。问题是重构这种事情的方式实际上取决于你的代码,它在做什么以及你想要完成什么。如果你曾说过你在检查类型这些条件中的对象,我们可以抛出一个类似'使用多态性'的答案,但有时你实际上只需要一些if语句,有时候这些语句可以被重构为某些东西更简单。如果没有代码示例,很难说您处于哪个类别。

2

几年前,一位教练告诉我,3是一个幻数。并且,当他将它应用于其他语句时,他建议如果我需要更多3个if,那么我应该使用case语句。

 
    switch (testValue) 
    { 
     case = 1: 
     // do something 
     break; 
     case = 2: 
     // do something else 
     break; 
     case = 3: 
     // do something more 
     break; 
     case = 4 
     // do what? 
     break; 
     default: 
     throw new Exception("I didn't do anything"); 
    } 

如果你嵌套的if语句超过3深,那么你应该把它作为一个迹象,有更好的方法。可能像Avirdlg建议的那样,将嵌套的if语句分成一个或多个方法。如果你觉得自己绝对坚持使用多个if-else语句,那么我会将所有if-else语句包装到一个单一的方法中,这样它就不会让其他代码变得难看。

+0

是的,但是switch语句的查询行为与if语句的顺序行为之间的关系也很重要。 – 2010-10-05 12:51:38

0

在简单的情况下,你应该能够基本功能分解得到解决。对于更复杂的场景,我使用Specification Pattern取得了巨大成功。

8

好问题。 “条件复杂性”是一种代码味道。 Polymorphism是你的朋友。

当条件逻辑很容易理解并且包含在几行代码中时,它就处于幼年时期的无辜状态。不幸的是,它很少老化。你实现了几个新功能,并且突然你的条件逻辑变得复杂和膨胀。 [约书亚凯雷夫斯基:重构图案]

如果块要学会使用Guard Clauses,则可以采取的最简单的措施之一是避免嵌套。

double getPayAmount() { 
if (_isDead) return deadAmount(); 
if (_isSeparated) return separatedAmount(); 
if (_isRetired) return retiredAmount(); 
return normalPayAmount(); 
}; 

我已经找到其他的事情简化的东西非常好,并且使你的代码自我文档,是Consolidating conditionals。与条件表达式相关

double disabilityAmount() { 
    if (isNotEligableForDisability()) return 0; 
    // compute the disability amount 

其他有价值refactoring技术包括Decompose ConditionalReplace Conditional with VisitorSpecification PatternReverse Conditional

+3

如果条件检查对象的类型,那么多态性可能仅用于消除if语句。如果你正在检查一个值多态性可能不是答案。但是,你继续提供其他建议,所以不要在这里冷静下来。不过,我认为在你的帖子中提及多态性评论时,可能会提到类型检查。 – 2009-10-24 23:06:21

1

不是C#的答案,但你可能会想要模式匹配。通过模式匹配,您可以接受多个输入,并在所有输入上进行同时匹配。例如(F#):

let x= 
    match cond1, cond2, name with 
    | _, _, "Bob"  -> 9000 // Bob gets 9000, regardless of cond1 or 2 
    | false, false, _ -> 0 
    | true, false, _ -> 1 
    | false, true, _ -> 2 
    | true, true, "" -> 0 // Both conds but no name gets 0 
    | true, true, _ -> 3 // Cond1&2 give 3 

您可以表达任意组合,以创建匹配(这只是皮毛)。但是,C#不支持这一点,我怀疑它会很快。同时,有一些尝试在C#中进行尝试,例如:http://codebetter.com/blogs/matthew.podwysocki/archive/2008/09/16/functional-c-pattern-matching.aspx。谷歌可以出现更多;也许一个人会适合你。