Храните оператора в переменной

Есть ли способ сохранить оператор внутри переменной? Я хочу сделать что-то вроде этого (псевдокод):

void MyLoop(int start, int finish, operator op)
{
    for(var i = start; i < finish; op)
    {
        //do stuff with i
    }
}

Тогда я мог бы вызвать этот метод следующим образом:

MyLoop(15, 45, ++);
MyLoop(60, 10, --);

Есть ли что-то подобное в С#?

Ответ 1

Я полагаю, что-то вроде этого. Вы не определяете оператор, а функцию (лямбда), которая делает это для вас.

void MyLoop(int start, int finish, Func<int, int> op)
{
    for(var i = start; i < finish; i = op(i))
    {
        //do stuff with i
    }
}

Тогда я мог бы вызвать этот метод следующим образом:

MyLoop(15, 45, x => x+1);
MyLoop(60, 10, x => x-1);

Ответ 2

Используйте Function delegate;

Инкапсулирует метод, который имеет один параметр и возвращает значение тип, заданный параметром TResult.

void MyLoop(int start, int finish, Func<int, int> op)
{
    for(var i = start; i < finish; i = op(i))
    {
        //do stuff with i
    }
}

Тогда;

MyLoop(15, 45, x => ++x);
MyLoop(60, 10, x => --x);

Вот DEMO.

Ответ 3

используйте что-то вроде Func<int, int> op

или измените тип op на строку, затем проверьте значение и в соответствии с этим постройте свой цикл for, как:

void MyLoop(int start, int finish, string op)
{
    if ((op.Equals("++") && (start < finish))
    {
      for(var i = start; i < finish; i++)
      {
          //processMethod(i)
      }
    }
    else if ((op.Equals("--") && (start > finish))
    {
      for(var i = start; i < finish; i--)
      {
          //processMethod(i)
      }
    }
}

Ответ 4

Вы можете обернуть операторы регулярными методами и использовать делегаты.

Ответ 5

public class Program {
    public static void Main(String[] args) {
        Looper(x => x + 1);
        Looper(x => ++x);
        //Looper(x => x++); will not works
        Looper(x => x * 2);
    }

    public static void Looper(Func<int, int> op) {
        for (int i = 1; i < 10; i = op(i)) {
            Console.WriteLine(i);
        }
        Console.WriteLine("----------");
    }

} 

Ответ 6

Я пробовал использовать другой подход, используя класс, определяющий операторы и доступ через рефлексию - т.е. вы можете хранить своих операторов в виде строк. Это также позволяет использовать реляционные операторы.

class Program
{
    static void Main(string[] args)
    {
        Operators ops = new Operators();
        object result = ops.Use("LessOrEqual", new object[] {3,2}); // output: False
        Console.WriteLine(result.ToString());

        result =  ops.Use("Increment", new object[] {3}); // output: 4
        Console.WriteLine(result.ToString());
        Console.ReadKey();
    }
}

public class Operators
{
    public object Use(String methodName, Object[] parameters)
    {
        object result;
        MethodInfo mInfo = this.GetType().GetMethod(methodName);
        result = mInfo.Invoke(this, parameters); // params for operator, komma-divided
        return result;
    }


    public bool LessOrEqual(int a, int b)
    {
        if (a <= b)
        {
            return true;
        }
        else
        {
            return false; 
        }  
    }

    public int Increment(int a)
    {
        return ++a;
    }
}