分配 lambda 表达式会导致以后不会执行该表达式
本文关键字:表达式 执行 lambda 分配 | 更新日期: 2023-09-27 17:56:59
我似乎在执行之前分配给变量的 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) 如何获得我想要的输出?
在代码中不使用表达式。
你的代码是这样的:
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);
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);
}
您不是在调用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));
}