C#:有没有办法将表达式用作变量/参数?

时间:2009-04-15 21:20:00

标签: c#

我想知道是否可以在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语句?

5 个答案:

答案 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命名空间作为允许用户扩展应用程序的更安全的方式。