使用if - else if重构foreach到LINQ的结构

时间:2011-10-19 11:56:08

标签: c# linq refactoring

我有这个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的电话就可以逃脱的方式吗?正如我现在所知,我需要在||的另一侧将其称为倒置。

2 个答案:

答案 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中所写的内容。