5

我似乎无法执行之前分配给变量的 lambda 表达式。这是我整理的一个小型 C# 示例程序:

public class Program
{
    public static void Main(string[] args)
    {
        int[] notOrdered = { 3, 2, 5, 8, 1, 4, 7, 9, 6 };
        Print(notOrdered);
        
        IEnumerable<int> ascOrdered = Order(notOrdered, true);
        Print(ascOrdered);

        IEnumerable<int> descOrdered = Order(notOrdered, false);
        Print(descOrdered);
    }
    
    static IEnumerable<T> Order<T>(IEnumerable<T> enumerables, bool ascending)
    {
        Expression<Func<T, object>> selector = (z) => z; // simple for demo purposes; pretend it's complex
        if (ascending)
            return enumerables.OrderBy(z => selector);
        else
            return enumerables.OrderByDescending(z => selector);
    }
    
    static void Print<T>(IEnumerable<T> enumerables)
    {
        foreach(T enumerable in enumerables)
            Console.Write(enumerable.ToString() + " ");
        Console.WriteLine();
    }
}

我希望它产生这个输出:

3 2 5 8 1 4 7 9 6

1 2 3 4 5 6 7 8 9

9 8 7 6 5 4 3 2 1

但是,令人困惑的是,它会产生以下输出:

3 2 5 8 1 4 7 9 6

3 2 5 8 1 4 7 9 6

3 2 5 8 1 4 7 9 6

基本上,我只是希望能够将相同的表达式传递给两个不同的排序操作,而不必输入两次,因此我selector事先将其分配给它。我有一个真实的用例,其中 lambda 表达式真的很长/很乱,我不想复制混乱,我宁愿只引用一个变量,就像我在这里一样。

那么,a)是什么导致了电流输出?b)我怎样才能得到我想要的输出?

4

3 回答 3

9

在您的代码中,您不使用表达式。

你的代码是这样的:

object selector = new object();
if (ascending)
    return enumerables.OrderBy(z => selector);
else
    return enumerables.OrderByDescending(z => selector);

您的代码应该没有表达式:

Func<T, object> selector = (z) => z;
if (ascending)
    return objects.OrderBy(selector);
else
    return objects.OrderByDescending(selector);

但是,如果您真的想要一个表达式(出于测试目的或其他任何目的),请先编译它:

Expression<Func<T, object>> selector = (z) => z;
var compiledExpression = selector.Compile();
if (ascending)
    return objects.OrderBy(compiledExpression);
else
    return objects.OrderByDescending(compiledExpression);
于 2013-02-01T21:57:37.417 回答
7

a) 现在,您是按Expression<Func<T,object>>(实际的表达式实例)而不是按对象本身排序的。这有效地使排序始终使用相同的对象进行排序,这意味着 order by 子句不会改变任何内容(所有项目都是“相等的”,因为它们等于表达式的同一实例)。

b)我相信你想要:

static IEnumerable<T> Order<T>(IEnumerable<T> enumerables, bool ascending)
{
    if (ascending)
        return enumerables.OrderBy(z => z);
    else
        return enumerables.OrderByDescending(z => z);
}
于 2013-02-01T21:57:46.490 回答
1

您没有调用selector,只是比较表达式的实例。正确的方法应该是

static IEnumerable<T> Order<T>(IEnumerable<T> enumerables, bool ascending)
{
    Func<T, object> selector = (z) => z;
    if (ascending)
        return enumerables.OrderBy(z => selector(z));
    else
        return enumerables.OrderByDescending(z => selector(z));
}
于 2013-02-01T22:03:04.977 回答