写一个Switch案例

时间:2013-02-15 13:11:13

标签: c# linq switch-statement

任何人都可以建议我,有没有更好的方法来编写下面的代码使用Swich案例或任何(谢谢大家在这里提出宝贵的建议我在Linq查询中使用它,我观察到它包含不同的一些修改产品名称)

    from p in l_list
    where ((LicenceType == "Full" && SystemType == "Single") && p.ProductName != "Full DoubleProduct ")
       || ((LicenceType == "Full" && SystemType == "Multiple") && p.ProductName != "Full SingleProduct")
       || ((LicenceType == "Partial" && SystemType == "Single") && p.ProductName != "Locked DoubleProduct") 
       || ((LicenceType == "Partial" && SystemSize == "Multiple") && p.ProductName != "Locked SingleProduct")
       || ((LicenceType == "Locked" && SystemSize == "Single") && p.ProductName != "Locked DoubleProduct") 
       || ((LicenceType == "Locked" && SystemType == "Multiple") && p.ProductName != "Locked SingleProduct")

5 个答案:

答案 0 :(得分:6)

这个可怕的布尔条件描述了数据对象子集之间共享的一些共同质量。确定质量并给它一个描述性的名称。

然后,通过数据对象上的属性公开该数量的值,或者编写执行相同操作的扩展方法。最后,使用此访问器替换现有条件。

例如,如果质量名称是“友好”,那么您可以这样做:

where model.IsFriendly // property

或者这个:

where model.IsFriendly() // extension method BusinessRules.IsFriendly(Model m)

答案 1 :(得分:4)

看起来您可以通过“分解”许可证类型来简化您的表达,并观察条件归结为更简单

(
(SystemType == "Single"   && p.ProductName != "DoubleProduct") ||
(SystemType == "Multiple" && p.ProductName != "SingleProduct")
) &&
(
LicenceType == "Full"  ||
LicenceType == "Partial" ||
LicenceType == "NotApplicable"
)

如果除了"Full""Partial""NotApplicable"之外没有许可证类型,您可以丢弃第二个条款以获取

的最终条件
(SystemType == "Single"   && p.ProductName != "DoubleProduct") ||
(SystemType == "Multiple" && p.ProductName != "SingleProduct")

编辑:通常情况下,当您有这样复杂的多部分条件时,您可以做的最好的事情是提取常见的子表达式,并尝试减少条件数量。根本问题在于,您试图在代码中表达“线性”具有多维度的条件;这种“折叠”导致代码难以阅读。

解决此问题的一种方法是在表格中“编码”您的条件,如下所示:

var conditions = new[] {
    new[] { "Full",          "Single",   "Full DoubleProduct"    }
,   new[] { "Full",          "Multiple", "Full SingleProduct"    }
,   new[] { "Partial",       "Single",   "Locked DoubleProduct"  }
,   new[] { "Partial",       "Multiple", "Locked SingleProduct"  }
,   new[] { "NotApplicable", "Single",    "Locked DoubleProduct" }
,   new[] { "NotApplicable", "Multiple", "Locked SingleProduct"  }
};

现在你可以在这样的条件下使用它:

Where (p => conditions.Any(cond =>
    cond[0] == p.LicenceType
 && cond[1] == p.SystemType
 && cond[2] != p.ProductName
))

这种方法的优点是条件为程序的读者“制表”,并且可以通过添加新行轻松扩展。缺点是您不能再对IQueryable源运行查询,而不会将部分结果存入内存。

答案 2 :(得分:0)

您可以使用标志来指示对象或属性具有的值。

[Flags]
enum MyEnum
{
    val1 = 0x01,
    val2 = 0x02,
    val3 = 0x04
}

您可以使用按位运算符(&&,||)来检查值。请参阅here

答案 3 :(得分:0)

您可以将条件“编码”为数组(状态矩阵),然后使用foreach / for和flags。

另一种可能的解决方案是bash.d已经给出 - 使用位域。如果你真的需要,你可以进一步结合两者

我自己避免使用重复的字符串(比如“Full”),而是将它们放在常量中以避免出错并提高可读性(有时)。

当操作数具有相同的优先级时,您也不需要使用括号,例如,(a == b && c == d) && e == f不需要使用支架。

最后,但并非最不重要的是,您可以尝试反转逻辑,这可能会简化条件,例如(a || b || c) = !(!a && !b && !c)。如果您正在处理可能条件的已知子集,那么这可能特别有用,然后您可以“优化”它。

答案 4 :(得分:0)

在Linq中,您可以调用外部函数。 那你为什么不把“业务逻辑”从查询中移出来呢? 即你可以创建一个方法

bool IsLincensedForXXX(Product p)

并在LINQ表达式中使用它:

from p in l_list where IsLincensedForXXX(p)

我认为它更清洁,更容易保留和重复使用。