将两个循环函数合二为一

时间:2013-01-15 02:18:55

标签: c# refactoring

我有一个定义列表和两个循环函数的类,它们查找列表中具有某些属性的项。这两个循环函数可以组合成一个更通用的循环函数,它将内部Bar.Function()作为参数吗?

class Foo {
    List<Bar> bar;

    List<int> SomeFunc() {
        List<int> list;
        for (i...) {
           if (bar[i].IsSomething()) {
               list.Add(i);
           }
        }
        return list;
    }


    List<int> SomeOtherFunc() {
        List<int> list;
        for (i...) {
           if (bar[i].IsSomethingElse()) {
               list.Add(i);
           }
        }
        return list;
    }

}

3 个答案:

答案 0 :(得分:4)

是的,如果您使用lambdas,这很容易:

class Foo 
{
        List<Bar> bar;

        List<int> SomeFunc()
        {
            return LoopedTest(b => b.IsSomething());
        }


        List<int> SomeOtherFunc()
        {
            return LoopedTest(b => b.IsSomethingElse());
        }

        private List<int> LoopedTest(Predicate<Bar> test)
        {
            List<int> list = new List<int>();
            for (int i = 0; i < bar.Count; i++)
            {
                if (test(bar[i]))
                {
                    list.Add(i);
                }
            }
            return list;
        }

}

正如其他人所提到的,在这个特殊情况下,已经有一个相对简洁的构造用于你正在进行的过滤(改进了phoog的建议):

return IEnumerable.Range(0, bar.Count).Where(i => bar[i].IsSomething()).ToList();

您还可以将这两种解决方案结合起来,以获得一些非常干净的代码:

class Foo 
{
        List<Bar> bar;

        List<int> SomeFunc()
        {
            return FindIndexes(b => b.IsSomething());
        }

        List<int> SomeOtherFunc()
        {
            return FindIndexes(b => b.IsSomethingElse());
        }

        private List<int> FindIndexes(Predicate<Bar> test)
        {
            return IEnumerable.Range(0, bar.Count).Where(i => test(bar[i])).ToList();
        }
}

答案 1 :(得分:0)

简单的LINQ调用如何:

 List<int> res = list.Select(x => x.SomeFunc).Union(list.Select(y => y.SomeFunc2))

答案 2 :(得分:-1)

如果您在匹配索引列表之后作为获取项目列表的前兆,您可以使用Linq:

var selection = bar.Where(b => b.IsSomething()).ToList();

由于这只是Linq的一个声明,你可能不需要将它放在自己的方法中,但是如果你这样做了,那么看起来就是这样:

private List<Bar> SomeFunc(Predicate<Bar> test)
{
    return bar.Where(test).ToList();
}

如果你真的在追踪指数之后,那么对Linq来说,它会是这样的:

var selection = bar.Select((b, i) => new { b, i })
                .Where(x => x.b.IsSomething())
                .Select(x => x.i)
                .ToList();

并考虑到一个方法,即:

private List<Bar> SomeFunc(Predicate<Bar> test)
{
    return bar.Select((b, i) => new { b, i })
                .Where(x => test(x.b))
                .Select(x => x.i)
                .ToList();
}