我想知道是否可以在C#中使用表达式作为变量/参数。我想做这样的事情:
int x = 0;
public void g()
{
bool greaterThan = f("x>2");
bool lessThan = f("x<2");
}
public bool f(Expression expression)
{
if(expression)
return true;
else
return false;
}
这是我不想做的事情:
int x = 0;
public void g()
{
bool greaterThan = f(x, '<', 2);
}
public bool f(int x, char c, int y)
{
if(c == '<')
return x < y;
if(c == '>')
return x > y;
}
我真正得到的是一种方法,可以使用每个开关或一系列if语句:&lt; &GT; &lt; =&gt; = ==!=。有办法吗?
编辑:假设表达式是一个字符串,例如“x&lt; 2”。有没有办法从字符串转到谓词而不使用条件上的一系列if语句?
答案 0 :(得分:11)
它很可能,只是没有你的确切语法。
int x = 0;
public void g()
{
bool greaterThan = f(i => i > 2, x);
bool lessThan = f(i => i < 2, x);
}
public bool f(Func<int,bool> expression, int value)
{
return expression(value);
}
实际上,这应该更接近你想要的。
int x = 0;
public void g()
{
bool greaterThan = f(() => x > 2);
bool lessThan = f(() => x < 2);
}
public bool f(Func<bool> expression)
{
return expression();
}
如果你想说f("x < 2")
,那几乎是不可能的。忽略解析它(可能会讨厌),你必须捕获x的值,但它只是f
的一个字符,这使它几乎不可能。
答案 1 :(得分:9)
如果你真的想传递代码,你需要一个谓词:
int x = 0;
public void g()
{
bool greaterThan = f(i => i>2, x);
bool lessThan = f(i => i<2, x);
}
public bool f(Predicate<int> expression, int value)
{
return expression(value);
}
否则,如果您只是在第一个示例中用bool
替换Expression
,那么您的代码就可以正常编译:
int x = 0;
public void g()
{
bool greaterThan = f(x>2);
bool lessThan = f(x<2);
}
public bool f(bool expression)
{
if(expression)
return true;
else
return false;
}
答案 2 :(得分:7)
除非我遗漏了什么......你为什么不这样做:
bool greaterThan = x > 5;
bool lessThan = x < 5;
布尔比较已经是表达式......
修改强>
因此,对于您的功能,只需传递bool
:
public void f(bool expression)
{
// expression is either true or false...
}
f(x<5); // called like this
答案 3 :(得分:2)
编辑:假设表达式是一个字符串,例如“x&lt; 2”。有没有办法从字符串转到谓词而不使用条件上的一系列if语句?
有些人已经提到过;如果您希望能够使用字符串,则需要解析。你真的不想编写自己的C#解析器,幸运的是,微软的一些人已经用Dynamic LINQ做了。
以下是您特定问题的解决方案:
public void g()
{
int x = 0;
bool greaterThan = f("x > 2", x);
bool lessThan = f("x < 2", x);
}
public bool f(string expression, int x)
{
ParameterExpression xExpr = Expression.Parameter(typeof(int), "x");
LambdaExpression e = DynamicExpression.ParseLambda(
new ParameterExpression[] { xExpr }, typeof(bool), expression);
return (bool)e.Compile().DynamicInvoke(x);
}
现在,显然,这会在字符串中出现最轻微的错误。你真的需要考虑你是否真的需要这个。但是,如果您真的这样做,可以使用DynamicExpression.ParseLambda
方法将字符串解析为LambdaExpression
。
答案 4 :(得分:0)
编辑:假设表达式是一个字符串,例如“x&lt; 2”。有没有办法从字符串转到谓词而不使用条件上的一系列if语句?
您可以使用几种技巧将字符串转换为.Net中的代码:CodeDom,Reflection.Emit,甚至可以编写shell中的编译器脚本。但是,这些都不像脚本语言中的快速eval()
那么简单,除非你真的知道你在做什么,否则这通常会在.Net中不受欢迎。
相反,.Net提供System.Addin
命名空间作为允许用户扩展应用程序的更安全的方式。