以ReSharper方式循环使用嵌套条件有什么好处?

时间:2014-01-28 13:13:49

标签: c# wpf loops foreach resharper

当使用内部具有嵌套条件的foreach循环时,我曾用以下方式编写:

foreach (RadioButton item in listOfRadioButtons)
{
    if (item.IsChecked == true)
    {
         // sometging
    }
}

但是我已经安装了ReSharper并建议将此循环更改为以下形式(删除if并使用lambda):

foreach (RadioButton item in listOfRadioButtons.Where(item => item.IsChecked == true))
{
    // something
}

根据我的经验,ReSharper方式将循环两次:一次生成过滤的IEnumerable,然后再循环.Where查询的结果。

我是对的?如果是这样,为什么ReSharper建议这样做?因为在我看来,第一个也更可靠。

注意:WPF RadioButton的默认IsChecked属性是Nullable bool,因此需要在条件内使用== true,.Value或强制转换来返回bool。

1 个答案:

答案 0 :(得分:5)

  

根据我的经验,ReSharper方式将循环两次:一次到   生成过滤后的IEnumerable,然后循环结果   。再次查询。

不,它只会循环一次。 Where不会循环您的集合 - 它只会创建迭代器,用于枚举您的集合。以下是LINQ解决方案的样子:

using(var iterator = listOfRadioButtons.Where(rb => rb.IsChecked == true))
{
    while(iterator.MoveNext())
    {
        RadioButton item = iterator.Current;
        // something
    }
}

您的原始代码更适合性能 - 您将避免创建委托并将其传递给WhereEnumerableIterator的实例,然后为源序列中的每个项执行委托。但你应该注意,正如@dcastro指出的那样,差异将非常小,并且在你必须优化这个特定循环之前不值得注意。

ReSharper建议的解决方案(可能)更易于阅读。我个人喜欢循环中的简单if条件。

UPDATE:Where迭代器可以简化为(也省略了一些接口)

public class WhereEnumerableIterator<T> : IEnumerable<T>, IDisposable
{
    private IEnumerator<T> _enumerator;
    private Func<T,bool> _predicate;

    public WhereEnumerableIterator(IEnumerable<T> source, Func<T,bool> predicate)
    {
        _predicate = predicate;
        _enumerator = source.GetEnumerator();
    }

    public bool MoveNext()
    {
        while (_enumerator.MoveNext())
        {
            if (_predicate(_enumerator.Current))
            {
                Current = _enumerator.Current;
                return true;
            }
        }

        return false;
    }

    public T Current { get; private set; }

    public void Dispose()
    {
        if (_enumerator != null)
            _enumerator.Dispose();
    }
}

这里的主要想法 - 它只在您要求它移动到下一个项目时枚举原始来源。然后迭代器转到原始源中的下一个项目并检查它是否与谓词匹配。如果找到匹配,则返回当前项并将枚举源置于保持状态。

因此,在您不会询问此迭代器中的项目之前,它不会枚举源代码。如果您将在此迭代器上调用ToList(),它将枚举源序列并返回所有匹配的项目,这些项目将保存到新列表中。