繁体   English   中英

用C#中的委托重载方法

[英]Overloading a method with delegates in c#

有什么办法可以使用委托“重载”函数? 我想拥有一个可以在构造函数中传递匿名函数并将其保存在成员变量中的系统。 数据类型并不是真正的问题,但是传递的函数可以具有一个或两个参数。 我试过在委托定义中使用(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为一个保留参数。 这些为匿名委托提供了类型安全性,并为您所需要的提供了一种清晰的方法,看起来像是Command或Strategy模式。

您还可以使用表达式来内联声明委托,如下所示:

public void InvokeAction(Action invoke)
{
    invoke();
}

InvokeAction(() => Console.WriteLine(...));

=>本质上是指“成”,如果您有参数,则可以在箭头之前声明它们:

(arg1, arg2) => ...

表达式和Action / Func几乎已从现代.Net编码中的匿名代表那里接手。

如果在类上具有Action类型的属性,则可以直接将其作为方法调用。

public Action Calc { get; set; }

Calc = () => Console.WriteLine(...);

Calc();

这将为您提供帮助。 在这种情况下,我刚刚将calc变量初始化为对象,它是所有类型(int,class,delegates等)的基本类型,在评估方法中,我已将其从对象转换为适当的类型。

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”,并且使用了强制转换来选择正确的操作(并检查是否提供了正确数量的操作数)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM