通过某些属性 - 代码改进

时间:2013-06-05 08:27:08

标签: c# linq c#-4.0

我有这样的方法:

public void DoSomething( .... , bool orderByX)
{

    if(orderByX)
    {
       foreach( ... OrderBy(x => x.Location.X))
       {
          ...
       }
    }
    else
    {
       foreach( ... OrderBy(x => x.Location.Y)
       {
          ...
       }
    }
}

我想避免if产生较少重复的代码(即只有一个foreach)。这可能吗?

感谢。

3 个答案:

答案 0 :(得分:15)

更好的方法是通过标准,按顺序排序。您可以使用下一个代码作为动机:

public void DoSomething<T>( .... , Func<Point, T> orderbySelector)
{
    foreach( ... OrderBy(p => orderbySelector(p.Location)))
    {
        ...
    }
}

现在你可以:

DoSomething(mySequence, point => point.X)

DoSomething(mySequence, point => point.Y) 

注意:您可以根据需要概括选择器(例如传递持有者或Location,而不是Point本身)。

此外,将bool作为排序条件传递会降低代码的可读性。例如,我不知道这个方法的作用,只需查看它的调用DoSomething(list, false),我必须看到方法签名才能知道false的语义是什么。使用命名参数DoSomething(list, orderByX : false)(可从 C#4.0 获得)会好得多,但如果我没有按X订购,那么,我怎么知道,然后我按Y排序?。这也限制了调用代码只有两个排序标准(你不想添加另一个排序标志,不是吗?)

因此,您需要打开您的意图,使DoSomething名称显示,您实际上是在命令处理。例如TraverseNodesOrderedBy(nodes, point => point.X)

答案 1 :(得分:3)

检查orderByX

的lambda表达式中的OrderBy
public void DoSomething( .... , bool orderByX)
{
    foreach( ... OrderBy(x => orderByX ? x.Location.X : x.Location.Y))
    {
      ...
    }
}

答案 2 :(得分:2)

LINQ查询是可组合的,这意味着您可以在执行它们之前构建它们:

public void DoSomething( .... , bool orderByX)
{
    var query = ... ;

    if (orderByX)
        query = ... .OrderBy(x => x.Location.X);
    else
        query = ... .OrderBy(x => x.Location.Y);

    foreach(var x in query) // deferred execution
    {
       ...
    }
}

除了其他可行的答案之外,还有另一种选择。