用if - else结构将foreach重构为LINQ

本文关键字:foreach 重构 LINQ 结构 if else | 更新日期: 2023-09-27 18:11:56

我有这个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 ?现在我需要把它命名为倒立在||的另一边

用if - else结构将foreach重构为LINQ

你是对的。如果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;

你是正确的。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;
}