c # — перегрузка выражения как параметра

#c# #lambda #delegates #overloading #func

#c# #лямбда #делегирует #перегрузка #функция

Вопрос:

Я хотел бы найти способ передать выражение (по возможности скомпилированное) в качестве аргумента функции. Выражение всегда будет возвращать один и тот же тип. Я хочу сохранить это выражение (функцию) в качестве параметра.

(Короткий) пример был бы очень признателен, если это возможно. 🙂 Я не знаю, возможно ли это.

Дополнительная информация: Ввод — это выражение, в котором должен быть исправлен только возвращаемый тип. Мне нужен способ определить этот тип прототипа.

Пример вызова метода:

 public delegate double[] ValueRetreiverFunc(params object[] anyNumberOfParams);

public class Class1
{
    public double[] Func()
    {
        double[] values = new double[1];
        values[0] = 2.0;
        return values;
    }
}

public class Class2
{
    public double[] Func(int n)
    {
        double[] values = new double[n];
        for (int c = 0; c < n; c  )
        {
            values[c] = 3.0;
        }
        return values;
    }
}

public class ClassTest
{
    public ValueRetreiverFunc ValueRetreiverFunc { get; set; }

    public void SetValueRetreiverFunc(ValueRetreiverFunc valueRetreiverFunc)
    {
        ValueRetreiverFunc = valueRetreiverFunc;
    }

    static void Test()
    {
        ClassTest classTest = new ClassTest();
        Class1 class1 = new Class1();
        Class2 class2 = new Class2();
        classTest.SetValueRetreiverFunc(()=> class1.Func());
        DoProcessArrayOfDouble(classTest.ValueRetreiverFunc());

        classTest.SetValueRetreiverFunc(()=> class2.Func(7));
        DoProcessArrayOfDouble(classTest.ValueRetreiverFunc());
    }
}
  

Комментарии:

1. Возможно, вам лучше проверить метод с помощью reflection, поскольку там вы можете легко предоставить динамический массив параметров.

2. Итак, вы говорите, что хотите иметь возможность передавать Func() или Func(int) методу в качестве одного и того же параметра?

3. aswyer: Спасибо, я, вероятно, так и сделаю. Но мне интересно, не подойдет ли для этого выражение класса?

4. Для Tejs: Отчасти верно. Вроде того. Я думаю, что это нечто большее. Это скорее выражение, потому что значение параметра фиксировано при присваивании. Вероятно, мой образец недостаточно хорош.

Ответ №1:

Я заглядывал далеко. Мне нужно использовать только «Func». Это работает как шарм. Это исправленный мой пример…

 public class Class1
{
    public double[] GetValues()
    {
        double[] values = new double[1];
        values[0] = 2.0;
        return values;
    }
}

public class Class2
{
    public double[] GetValues(int n)
    {
        double[] values = new double[n];
        for (int c = 0; c < n; c  )
        {
            values[c] = 3.0;
        }
        return values;
    }
}

public class ClassTest
{
    public Func<double[]> ValueRetreiverFunc;


    public void SetValueRetreiverFunc(Func<double[]> valueRetreiverFunc)
    {
        ValueRetreiverFunc = valueRetreiverFunc;
    }

    public static void Test()
    {
        ClassTest classTest = new ClassTest();
        Class1 class1 = new Class1();
        Class2 class2 = new Class2();
        classTest.SetValueRetreiverFunc(() => class1.GetValues());
        DoProcessArrayOfDouble(classTest.ValueRetreiverFunc());

        classTest.SetValueRetreiverFunc(() => class2.GetValues(7));
        DoProcessArrayOfDouble(classTest.ValueRetreiverFunc());
    }

    static void DoProcessArrayOfDouble(double[] doubleArray)
    {
        foreach(double d in doubleArray)
        {
            Debug.Print(d.ToString());
        }
    }

}
  

Ответ №2:

Единственное, что я могу придумать, это примерно так — вместо того, чтобы пытаться использовать делегат, определите интерфейс, и каждая реализация вернет все, что захочет.

 public interface IDoubleReturningClass
{
     double[] DoSomething(params object[] anyNumberOfParams);
}

public class Class1 : IDoubleReturningClass
{
     public double[] DoSomething(params object[] anyNumberOfParams)
     {
         double[] values = new double[1];
         values[0] = 2.0;
         return values;
     }
}

public class Class2 : IDoubleReturningClass
{
     public double[] DoSomething(params object[] anyNumberOfParams)
     {
         double[] values = new double[n];
         for (int c = 0; c < n; c  )
         {
             values[c] = 3.0;
         }
         return values;
     }
}

public class ClassTest
{
      public double[] Values { get; set; }

      public void SetValues(IDoubleReturningClass item)
      {
             Values = item.DoSomething( /* Your Params */);
      }
}
  

Комментарии:

1. Спасибо Tejs. Я думал об этом. Но интерфейс не смог выполнить задание. Это связано с тем фактом, что выражение определено с фиксированным значением в определенный момент времени, но должно быть одинаковым всякий раз, когда мы вызываем эту функцию. Интерфейс не смог запомнить значение. Может быть просто выражение (лямбда или другого типа).

Ответ №3:

Еще один способ решения проблемы, который показал мне мой коллега Омар… Просто с помощью делегата… Из-за разрешения лямбда компилятором…

 public class TestDelegate
{
    public delegate double[] ValueRetreiverFunc();
    // or  public Func<double[]> ValueRetreiverFunc;

    public class Class1
    {
        public double[] Func()
        {
            double[] values = new double[1];
            values[0] = 2.0;
            return values;
        }
    }

    public class Class2
    {
        public double[] Func(int n)
        {
            double[] values = new double[n];
            for (int c = 0; c < n; c  )
            {
                values[c] = 3.0;
            }

            return values;
        }
    }

    public class ClassTest
    {
        public ValueRetreiverFunc ValueRetreiverFunc { get; set; }

        public void SetValueRetreiverFunc(ValueRetreiverFunc valueRetreiverFunc)
        {
            ValueRetreiverFunc = valueRetreiverFunc;
        }

        public static void Test()
        {
            ClassTest classTest = new ClassTest();
            Class1 class1 = new Class1();
            Class2 class2 = new Class2();

            classTest.SetValueRetreiverFunc(() => class1.Func());
            DoProcessArrayOfDouble(classTest.ValueRetreiverFunc());
            classTest.SetValueRetreiverFunc(() => class2.Func(7));
            DoProcessArrayOfDouble(classTest.ValueRetreiverFunc());
        }

        static void DoProcessArrayOfDouble(double[] doubleArray)
        {
            foreach (double d in doubleArray)
            {
                Debug.Print(d.ToString());
            }
        }
    }
}