我有这个foreach循环:
var includedElements = new HashSet<int>();
foreach(var e in elements)
{
var include = false;
if(isTable(e.Key))
{
if(tables.ContainsKey(e.Key)
{
if(tables[e.Key].Elements
.Any(subElem => shouldBeIncluded(subElem.Key) ) )
{
include = true;
}
}
}
else if(shouldBeIncluded(e.Key))
{
include = true;
}
if(include){
includedElements.Add(e.Key);
DoSomeMoreStuff(e);
}
}
我试图将其重构为LINQ:
var query =
from e in elements
where
(
isTable(e.Key)
&& tables.ContainsKey(e.Key)
&& tables[e.Key].Elements
.Any(subElem => shouldBeIncluded(subElem.Key) )
) || (
!isTable(e.Key)
&& shouldBeIncluded(e.Key)
)
select e;
foreach(e in query){
includedElements.Add(e.Key);
DoSomeMoreStuff(e);
}
我不确定的是或条款。在我的脑海中,我需要包含!isTable(e.Key)
来处理外部if
/ else if
结构。
我的重构是否正确?这两个代码示例是否产生相同的逻辑功能?
这是一种我只能拨打isTable
的电话就可以逃脱的方式吗?正如我现在所知,我需要在||
的另一侧将其称为倒置。
答案 0 :(得分:5)
是的,你是对的。如果isTable
没有副作用(除了检查某些东西之外什么都不做)并且基于参数是确定性的(因此用e.Key调用它两次总是得到相同的值)。仍然可能(它可能是一个过早的优化......谁知道?)可能更好地保持它与原始if
更相似并使用三元运算符(? :
)所以不要重新检查isTable
var query =
from e in elements
where
isTable(e.Key) ?
tables.ContainsKey(e.Key) && tables[e.Key].Elements
.Any(subElem => shouldBeIncluded(subElem.Key) )
:
shouldBeIncluded(e.Key)
select e;
我要补充一点,如果您讨厌三元运算符,可以使用let
关键字:
var query =
from e in elements
let isT = isTable(e.Key)
where
( isT && tables.ContainsKey(e.Key) && tables[e.Key].Elements
.Any(subElem => shouldBeIncluded(subElem.Key) ) )
||
( !isT && shouldBeIncluded(e.Key) )
select e;
缓存isTable(e.Key)
答案 1 :(得分:0)
你是对的。 else if
表示if
条件不匹配,因此
if(A) {
if(B) {
if(C) {
include = true;
}
}
}
else if(D) {
include = true;
}
相当于
if(A) {
if(B) {
if(C) {
include = true;
}
}
}
if(!A && D) {
include = true;
}
相当于
if ((A && B && C) || (!A && D)) {
include = true;
}
这正是您在LINQ中所写的内容。