【C#】Action,Func,Predicate的使用,总结

Action和Func

相同点

  1. 都是delegate
  2. 都是泛型委托
  3. 都是最多有16个参数

不同点

  1. Action 无返回值,Func 有一个返回值

还有一个系统定义的委托Predicate,不常用,只能传一个参数并返回一个bool类型的值

Action和Func就是系统定义好的委托,其实我们也可以自己定义,但是如果每次使用都自己定义也太麻烦了,所以还是使用现成的

Action

无返回值

Action<int, int> action = new Action<int, int>(Add);
复制代码

定义一个Action,参数为两个int类型参数的方法

private static void Add(int a, int b)
{
    Console.WriteLine("{0} + {1} = {2}", a, b, a + b);
}
复制代码

Func

有一个返回值

Func<int, int, int> func = new Func<int, int, int>(Add2);
复制代码

前面两个int对应着Add2方法参数的a和b,第三个int为返回值

private static int Add2(int a, int b)
{
    return a + b;
}
复制代码

Predicate

传一个参数并返回一个bool类型的值

Predicate<bool> predicate = new Predicate<bool>(isEqual);
复制代码

private static bool isEqual(bool b)
{
    return b;
}
复制代码

结合 Lambda 表达式

Action

Action<int, int> action = (a, b) => { Console.WriteLine("{0} + {1} = {2}", a, b, a + b); };
复制代码

当语句块只有一条语句时,可以进一步简写成

 Action<int, int> action = (a, b) => Console.WriteLine("{0} + {1} = {2}", a, b, a + b);
复制代码

Func

Func<int, int, int> func = (a, b) => { return a + b; };
复制代码

进一步简写

Func<int, int, int> func = (a, b) => a + b;
复制代码

Predicate

Predicate<bool> predicate = (b) => { return b; };
复制代码

进一步简写

Predicate<bool> predicate = (b) => b;
复制代码

用作方法的参数

通常方法的参数都是一些常用的数据类型,比如int,string,bool等

如果我们想将一个语句块作为参数,使用普通的数据类型作为参数就行不通了,这时候可以用到委托了

一个简单的例子

定义一个两个数相加的方法,但是这两个数都是通过不同的运算方法得到的

private static int Add(Func<int> reslut1, Func<int> reslut2)
{
    int num1 = reslut1();

    int num2 = reslut2();

    int sum = num1 + num2;

    return sum;
}
复制代码

运用

这个运算过程可能是更复杂的过程

int a = 2, b = 3;

Add(() =>
{
    int sub = a - b;
    return sub;
}, () =>
{
    int nul = a * b;
    return nul;
});
复制代码

这个例子可能不太形象,举个更实用的例子

一个复杂一点的例子

如,现在执行一个发指令的方法,即上位机软件发送指令到下位机,由于经常发指令,所以把执行指令的方法写成一个模板方法

发指令的过程;
1.从数据库获取指令
2.对指令的参数进行赋值
3.执行指令(其中执行指令又分为发送与等待结果等)
4.对执行指令的结果进行解析

现在,用一个简单的例子模拟发指令的过程

先建立两个Model,一个存放指令,一个存放指令运行结果

/// <summary>
/// 指令
/// </summary>
public class Instruction
{
    /// <summary>
    /// 名称
    /// </summary>
    public string Name;
    /// <summary>
    /// 指令编号
    /// </summary>
    public int CurNo;
    /// <summary>
    /// 参数
    /// </summary>
    public byte[] Param;
}


/// <summary>
/// 指令执行详细信息
/// </summary>
public class OperateDetail
{
    /// <summary>
    /// 参数
    /// </summary>
    public byte[] Param;
}
复制代码

执行指令的模板方法

public static bool ExecuteTemplet(Func<Instruction> Ins, out OperateDetail reslut)
{
    reslut = new OperateDetail();

    Instruction model = Ins();

    //执行指令(省略) 将指令model发送到下位机
    //返回结果(省略) 从是数据库中查询结果赋值给reslut

    return true;
}
复制代码

模板方法写好了,

现在需要获取设置序列号,写一个设置序列号的方法,

其中调用模板方法,这样可以不用重复写执行指令和返回结果的方法

public static bool SetSN(string sn)
{
    sn = string.Empty;
    bool bExecute = ExecuteTemplet(() =>
    {
        Instruction ins = new Instruction();

        //从数据库中获取指令(省略)

        //对指令参数进行赋值
        ins.Param = Encoding.Default.GetBytes(sn);

        ins.CurNo = 1;

        return ins;
    }, out OperateDetail reslut);

    if (bExecute == false)
    {
        return false;
    }

    return true;
}
复制代码

现在有来一个方法,获取序列号

public static bool GetSN(out string sn)
{
    sn = string.Empty;
    bool bExecute = ExecuteTemplet(() =>
    {
        Instruction ins = new Instruction();

        //从数据库中获取指令(省略)

        //对指令参数进行赋值
        ins.CurNo = 1;

        return ins;
    }, out OperateDetail reslut);

    if (bExecute == false)
    {
        return false;
    }
    //解析结果
    sn = Encoding.Default.GetString(reslut.Param);

    return true;
}
复制代码

由这个两个方法,可以看出,利用Func作为方法的参数,可以定义模板方法,不用重复同样的代码,后期维护也简单

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享