C# convert a string for use in a logical condition

20,531

Solution 1

You could do something like this:

public static bool Compare<T>(string op, T x, T y) where T:IComparable
{
 switch(op)
 {
  case "==" : return x.CompareTo(y)==0;
  case "!=" : return x.CompareTo(y)!=0;
  case ">"  : return x.CompareTo(y)>0;
  case ">=" : return x.CompareTo(y)>=0;
  case "<"  : return x.CompareTo(y)<0;
  case "<=" : return x.CompareTo(y)<=0;
 }
}

Solution 2

EDIT

As JaredPar pointed out, my suggestion below won't work as you can't apply the operators to generics...

So you'd need to have specific implementations for each types you wanted to compare/compute...

public int Compute (int param1, int param2, string op) 
{
    switch(op)
    {
        case "+": return param1 + param2;
        default: throw new NotImplementedException();
    }
}

public double Compute (double param1, double param2, string op) 
{
    switch(op)
    {
        case "+": return param1 + param2;
        default: throw new NotImplementedException();
    }
}

ORIG

You could do something like this.

You'd also need to try/catch all this to ensure that whatever T is, supports the particular operations.

Mind if I ask why you would possibly need to do this. Are you writing some sort of mathematical parser ?

public T Compute<T> (T param1, T param2, string op) where T : struct
{
    switch(op)
    {
        case "+":
            return param1 + param2;
        default:
             throw new NotImplementedException();
    }
}

public bool Compare<T> (T param1, T param2, string op) where T : struct
{
    switch (op)
    {
        case "==":
             return param1 == param2;
        default:
             throw new NotImplementedException();
    }
}

Solution 3

No, it's not possible, and why the hell would you wnat to do this?

You could, of course, create a function like:

 public static bool Compare<T>(char op, T a, T b);

Solution 4

You should look into using .NET 3.5's Expression trees. You can build expressions manually into an expression tree (basically an AST), and then call Expression.Compile() to create a callable delegate. Your LogicRule.Test() method would need to build the Expression tree, wrap the tree in a LambdaExpression that takes the object your applying the rules too as an argument, calls Compile(), and invokes the resulting delegate.

Solution 5

I've done something similar to this with the help of:

http://flee.codeplex.com/

This tool can essentially evaulate a wide range of expressions. Basic usage would be to pass in a string like '3 > 4' and the tool would return false.

However, you can also create an instance of the evaluator and pass in object name/value pairs and it can be a little more intuitive IE: myObject^7 < yourObject.

There is a ton more functionality that you can dive into at the codeplex site.

Share:
20,531
Guilherme
Author by

Guilherme

Co-founder at Parrish Blake.

Updated on May 14, 2021

Comments

  • Guilherme
    Guilherme almost 3 years

    Is it possible to convert a string to an operator for use in a logical condition.

    For example

    if(x Convert.ToOperator(">") y) {}
    

    or

    if(x ">" as Operator y){}
    

    I appreciate that this might not be standard practice question, therefore I'm not interested in answers that ask me why the hell would want to do something like this.

    Thanks in advance

    EDIT: OK I agree, only fair to give some context.

    We have system built around reflection and XML. I would like to be able to say something like, for ease.

    <Value = "Object1.Value" Operator = ">" Condition = "0"/>
    

    EDIT: Thanks for your comments, I can't properly explain this on here. I guess my question is answered by "You can't", which is absolutely fine (and what I thought). Thanks for your comments.

    EDIT: Sod it I'm going to have a go.

    Imagine the following

    <Namespace.LogicRule Value= "Object1.Value" Operator=">" Condition="0">  
    

    This will get reflected into a class, so now I want to test the condition, by calling

    bool LogicRule.Test()
    

    That's the bit where it would all need to come together.

    EDIT:

    OK, so having never looked at Lambdas or Expressions I thought I would have a look after @jrista's suggestions.

    My system allows Enums to be parsed, so Expressions are attractive because of the ExpressionType Enum.

    So I created the following class to test the idea:

        public class Operation
        {
            private object _Right;
            private object _Left;
            private ExpressionType _ExpressionType;
            private string _Type;
    
            public object Left
            {
                get { return _Left; }
                set { _Left = value; }
            }
    
            public object Right
            {
                get { return _Right; }
                set { _Right = value; }
            }
    
            public string Type
            {
                get { return _Type; }
                set { _Type = value; }
            }
    
            public ExpressionType ExpressionType
            {
                get { return _ExpressionType; }
                set { _ExpressionType = value; }
            }
    
            public bool Evaluate()
            {
                var param = Expression.Parameter(typeof(int), "left");
                var param2 = Expression.Parameter(typeof(int), "right");
    
                Expression<Func<int, int, bool>> expression = Expression.Lambda<Func<int, int, bool>>(
                   Expression.MakeBinary(ExpressionType, param, param2), param, param2);
    
                Func<int, int, bool> del = expression.Compile();
    
                return del(Convert.ToInt32(Left), Convert.ToInt32(Right));
    
            }
        }
    

    Obviously this will only work for Int32 right now and the basic ExpressionTypes, I'm not sure I can make it generic? I've never use Expressions before, however this seems to work.

    This way can then be declared in our XML way as

    Operation<Left="1" Right="2" ExpressionType="LessThan" Type="System.Int32"/>