#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());
}
}
}
}