在 C# 中使用委托重载方法
Overloading a method with delegates in c#
有什么方法可以 "overload" 使用委托的函数吗?我想要一个系统,我可以在构造函数中传递匿名函数并将其保存在成员变量中。数据类型并不是真正的问题,但传递的函数可以有一个或两个参数。我试过在委托定义中使用 (params double[] vals),但这会使传递的匿名函数复杂化,并允许使用比应允许的更多的参数。
所以我创建了两个空方法来保存这两种类型。例如:
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public evalDelegate eval; //method used for two value inputs. Assigned in constructor.
public calcDelegate calc; //method used for single value input. Assigned in constructor.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
eval = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return calc(values[0]);
}
else
{
return eval(values[0], values[1]);
}
//more stuff
}
}
最终,我想做的更像这样:
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public ???????? calc; //method that does the passed function.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
eval = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return calc(values[0]);
}
else
{
return calc(values[0], values[1]);
}
//more stuff
}
}
我对 C# 不是很熟悉,但是肯定有一种方法可以做这样的事情,而不必定义一个委托的实例或另一个将不被使用的实例。
.Net 提供了一些开箱即用的有用委托类型;即 Action 用于返回 void 的方法,Func 用于保留参数。这些提供了匿名委托的类型安全,并提供了一种干净的方法来满足您的需要,这似乎类似于命令或策略模式。
您还可以使用表达式来声明内联委托,如下所示:
public void InvokeAction(Action invoke)
{
invoke();
}
InvokeAction(() => Console.WriteLine(...));
=> 本质上意味着 'into',如果你有参数,你会在箭头之前声明它们:
(arg1, arg2) => ...
在现代 .Net 编码中,表达式和 Action/Func 几乎完全取代了匿名委托。
如果您在 class 上有一个 属性 类型的 Action,您可以直接将其作为方法调用。
public Action Calc { get; set; }
Calc = () => Console.WriteLine(...);
Calc();
这对你有帮助。在这里,我刚刚将您的 calc 变量初始化为对象,它是所有类型(int、class、委托等)的基本类型,并且在评估方法中我将它从对象转换为适当的类型。
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public object calc; //method that does the passed function.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return (calc as calcDelegate)(values[0]);
}
else
{
return (calc as evalDelegate)(values[0], values[1]);
}
//more stuff
}
}
我会把我的帽子扔进戒指...
以下是您将如何使用 Func。
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public object func;
//constructor initializes all variables.
public OpWrapper(int p, Func<double, double> f, bool a = false)
{
//No need to pass in o, we can infer from context that its a single parameter
operands = 1;
precedence = p;
rightAssoc = a;
func = f;
}
//overloaded constructor assigns the proper method.
public OpWrapper(int p, Func<double, double, double> f, bool a = false)
{
//No need to pass in o, we can infer from context that its a double parameter
operands = 2;
precedence = p;
rightAssoc = a;
func = f;
}
public double evaluate(params double[] values)
{
if (values.Length != operands)
throw new InvalidOperationException("Invalid number of operands");
//do stuff
if (operands == 1)
{
return ((Func<double, double>)func)(values[0]);
}
else
{
return ((Func<double, double, double>)func)(values[0], values[1]);
}
//more stuff
}
}
请注意,我从调用中删除了 "o",并且我使用转换来选择正确的操作(并检查是否提供了正确数量的操作数)。
有什么方法可以 "overload" 使用委托的函数吗?我想要一个系统,我可以在构造函数中传递匿名函数并将其保存在成员变量中。数据类型并不是真正的问题,但传递的函数可以有一个或两个参数。我试过在委托定义中使用 (params double[] vals),但这会使传递的匿名函数复杂化,并允许使用比应允许的更多的参数。
所以我创建了两个空方法来保存这两种类型。例如:
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public evalDelegate eval; //method used for two value inputs. Assigned in constructor.
public calcDelegate calc; //method used for single value input. Assigned in constructor.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
eval = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return calc(values[0]);
}
else
{
return eval(values[0], values[1]);
}
//more stuff
}
}
最终,我想做的更像这样:
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public ???????? calc; //method that does the passed function.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
eval = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return calc(values[0]);
}
else
{
return calc(values[0], values[1]);
}
//more stuff
}
}
我对 C# 不是很熟悉,但是肯定有一种方法可以做这样的事情,而不必定义一个委托的实例或另一个将不被使用的实例。
.Net 提供了一些开箱即用的有用委托类型;即 Action 用于返回 void 的方法,Func 用于保留参数。这些提供了匿名委托的类型安全,并提供了一种干净的方法来满足您的需要,这似乎类似于命令或策略模式。
您还可以使用表达式来声明内联委托,如下所示:
public void InvokeAction(Action invoke)
{
invoke();
}
InvokeAction(() => Console.WriteLine(...));
=> 本质上意味着 'into',如果你有参数,你会在箭头之前声明它们:
(arg1, arg2) => ...
在现代 .Net 编码中,表达式和 Action/Func 几乎完全取代了匿名委托。
如果您在 class 上有一个 属性 类型的 Action,您可以直接将其作为方法调用。
public Action Calc { get; set; }
Calc = () => Console.WriteLine(...);
Calc();
这对你有帮助。在这里,我刚刚将您的 calc 变量初始化为对象,它是所有类型(int、class、委托等)的基本类型,并且在评估方法中我将它从对象转换为适当的类型。
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public object calc; //method that does the passed function.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return (calc as calcDelegate)(values[0]);
}
else
{
return (calc as evalDelegate)(values[0], values[1]);
}
//more stuff
}
}
我会把我的帽子扔进戒指...
以下是您将如何使用 Func。
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public object func;
//constructor initializes all variables.
public OpWrapper(int p, Func<double, double> f, bool a = false)
{
//No need to pass in o, we can infer from context that its a single parameter
operands = 1;
precedence = p;
rightAssoc = a;
func = f;
}
//overloaded constructor assigns the proper method.
public OpWrapper(int p, Func<double, double, double> f, bool a = false)
{
//No need to pass in o, we can infer from context that its a double parameter
operands = 2;
precedence = p;
rightAssoc = a;
func = f;
}
public double evaluate(params double[] values)
{
if (values.Length != operands)
throw new InvalidOperationException("Invalid number of operands");
//do stuff
if (operands == 1)
{
return ((Func<double, double>)func)(values[0]);
}
else
{
return ((Func<double, double, double>)func)(values[0], values[1]);
}
//more stuff
}
}
请注意,我从调用中删除了 "o",并且我使用转换来选择正确的操作(并检查是否提供了正确数量的操作数)。