我可以将一个嵌套的lambda表达式存储在Dictionary中吗?
本文关键字:存储 表达式 lambda Dictionary 中吗 嵌套 一个 我可以 | 更新日期: 2023-09-27 18:14:14
我想在c#中将字符串解析为lambda表达式,例如,将"lt 5"
解析为x => x < 5
,以便我可以将其用作Enumerable.Where
的参数:
static void Main(string[] args)
{
Enumerable
.Range(0,10)
.Select(x => (double)x)
.Where(Parse("lt 5"))
.ToList()
.ForEach(System.Console.WriteLine);
}
private const List<Tuple<List<string>, Func<double, Func<double, bool>>>> operationList =
new Dictionary<string, Func<double, Func<double, bool>>>()
{ { "lt <", val => ( x => x < val ) }
, { "le <=", val => ( x => x <= val ) }
, { "eq = ==" , val => ( x => x == val ) }
, { "ne != <>", val => ( x => x != val ) }
, { "ge >=", val => ( x => x >= val ) }
, { "gt >", val => ( x => x > val ) } }
.Select(kv =>
new Tuple<
List<string>,
Func<double, Func<double, bool>>>(
kv.Key.Split(' ').ToList(),
kv.Value))
.ToList();
public static Func<double, bool> Parse(string raw)
{
var fields = raw.Split(' ');
var predKey = fields[0].ToLower();
var predBuilder = operationList.FirstOrDefault(tp =>
tp.Item1.FirstOrDefault(key => key.Equals(predKey)) != null);
return predBuilder.Item2(double.Parse(fields[1]));
}
首先,我做了一个operationList
,它存储一个元组,其中Item1
描述了操作符的所有别名,Item2
存储了操作符的curry版本。
则Parse
将字符串lt 5
拆分为["lt","5"]
,并根据关键字lt
搜索操作。
最后,如果我能找到操作,5
将部分应用于它,结果将是一个lambda表达式x => x < val
。
然而,编译器对{ "lt <", val => ( x => x < val ) }
很生气,并抱怨"表达式不能包含匿名方法或lambda表达式"。
我不知道这是什么意思,也不知道如何让事情工作。
将const
改为readonly
,改为static
,如下所示:
private readonly static List<Tuple<List<string>, Func<double, Func<double, bool>>>> operationList =
new Dictionary<string, Func<double, Func<double, bool>>>()
{ { "lt <", val => ( x => x < val ) }
, { "le <=", val => ( x => x <= val ) }
, { "eq = ==" , val => ( x => x == val ) }
, { "ne != <>", val => ( x => x != val ) }
, { "ge >=", val => ( x => x >= val ) }
, { "gt >", val => ( x => x > val ) } }
.Select(kv =>
new Tuple<
List<string>,
Func<double, Func<double, bool>>>(
kv.Key.Split(' ').ToList(),
kv.Value))
.ToList();
在c#中,const关键字用于表示编译时间常量,但在您的示例中,列表是在运行时使用LINQ计算的。
在c#中const
的值总是静态的,将其设置为只读会将字段的作用域更改为instance。
注意,列表的内容可能在执行过程中发生变化,readonly
不会阻止您删除和添加元组到列表中。考虑使用ReadOnlyCollection(它仍然不会阻止你修改它,只是会使它更难)或使用不可变集合(它不是.net BCL的一部分)