任何人都可以建议我,有没有更好的方法来编写下面的代码使用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")
答案 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)
我认为它更清洁,更容易保留和重复使用。