泛型委托Action和一些常见用法

泛型委托Action

Action的定义

  在.Net2.0里面,Action只有一个定义

public delegate void Action(T arg);
定义一个普通的委托格式是:
public delegate void PuTongWeiTuo(int a, int b);或者
public delegate string PuTongWeiTuo(int a, int b);

  在.Net3.5及以上,Action有4种定义

public delegate void Action(T arg);
public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);

  不同点是参数越来越多,相同点是,所有的Action都被定义为无返回值。Action的四种形式是:1参无返回、2参无返回、3参无返回、4参无返回。
  当然了,虽然.NET2.0没有定义其他的Action但是可以手动定义。想定义几个就定义几个。因为在不同的namespace,即便是跟一定定义过的Action重复了,也是可以的。

①public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
②public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
③public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
④public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
⑤public delegate void Action<T1>(T1 arg1);

  任何版本的.NET都可以这么定义。第一个定义了一个五参无返回且名字为Action的委托。后面四个将已经定义过的Action重新定义了一遍.

Action的其中一种使用场景

  我本人在项目开发中经常遇到一些通过服务器查询数据的情况。在实际项目开发中,模块化思想需要将查询模块和界面是分开。所以查询模块需要提供接口给界面使用,使得界面能够利用查询模块提供的接口进行数据查询。
  在上面描述的场景中,两个模块的交互就可以使用委托的方法来进行,而且这种方法要比其他方法的代码可读性更强,代码更容易阅读,一目了然。

场景实例

假设界面有如下需求: 从服务器获取某一年度天气状况为良好的所有日期(类型为DateTime)。

  从需求中可以确认:
  查询的条件是:“年份”,“天气状况”。
  查询的结果是:一组时间


  那么我们可以定义如下委托:

/// <summary>
/// 委托:获取年份为year的,空气质量为airCondition的所有日期。
/// </summary>
/// <param name="year">年份</param>
/// <param name="airCondition">true表示空气质量良好</param>
/// <returns></returns>
public delegate List<DateTime> GetDateList(int year, bool airCondition); 

  但是这样定义的委托在使用过程中有一个缺陷。就是如果网络差的时候,委托会一直一直等待结果回来,会导致界面卡死。使用多线程的方法也行不通,因为后面很快就要使用到查询回来的这些日期,还是要等待结果。
  可以加入回调的方法。

/// <summary>
/// 委托:获取年份为year的,空气质量为airCondition的所有日期。
/// </summary>
/// <param name="year">年份</param>
/// <param name="airCondition">true表示空气质量良好</param>
/// <param name="dateTimeResultListHandler">处理</param>
public delegate void GetDateList(int year, bool airCondition, Action<List<DateTime>> dateTimeResultListHandler); 

  在上面定义的委托的参数列表中还有一个委托Action,Action在上面说过,是一个有参无返回的函数。也就是说

Action<List> dateTimeResultListHandler

这个参数其实传过去的是一个没有返回值的函数,是仅有一个参数,且参数类型为List的函数。这个函数干嘛用呢。前两个参数分别是int year, bool airCondition这两个参数足够计算出结果List了。然后将计算出来的结果输入到dateTimeResultListHandler函数中,并且在执行函数dateTimeResultListHandler的过程中使用线程池技术。这样就不会阻塞主界面,主界面也不需要等待结果回来了。而是结果回来之后自行处理。
  这种情况也可以使用事件,接口来完成。但是使用委托更加的方便,代码的可读性也更强。
  可能有不少人并不知道“回调函数”中的“回调”是什么意思。在上面的例子中函数dateTimeResultListHandler并不第一时间执行,而是等目标函数返回结果之后来执行。这种方式就叫“回调”

结尾

  重要的事情说三遍,Action是泛型委托,Action是泛型委托,Action是泛型委托。区别于很多自己定义的委托。比如我们前面自己定义的GetDateList。我们在使用GetDateList的时候直接GetDateList();或者就行了GetDateList.Invoke();但是使用泛型委托的时候还必须要指定类型。
  定义和使用普通委托。

  • 普通委托示例一:

定义:
public delegate DateTime GetDate(int year);
使用:
var ret = GetDate(2019);
或者var ret = GetDate.Invoke(2019);


  定义和使用泛型委托。

  • 泛型委托示例一:
static void Main(string[] args)
{
    Action<string,string> BookAction = new Action<string,string>(Book);
    BookAction("百年孤独","北京大书店");
}
public static void Book(string BookName,string ChangJia)
{
    Console.WriteLine("我是买书的是:{0}来自{1}",BookName,ChangJia);
}
  • 泛型委托示例二:
getDataDelegate(AlarmLevel.Level1, new Action<List<AlarmResult>>((resultList) => this.Invoke(new MethodInvoker(() =>
{
    if (resultList.Count == 0) return;
    foreach (AlarmResult result in resultList)
    {
        DataRow row = _dataTable.NewRow();
        row["报警级别"] = result.AlarmLevel;
        row["设备名称"] = result.DevName;
        row["报警描述"] = result.AlarmInfo;
        row["报警时间"] = result.AlarmTime;
        row["报警次数"] = result.AlarmCount;
        row["是否确认"] = result.IsConfirm;

        this._dataTable.Rows.Add(row);
    }
    this.ultraGrid.Refresh();
    this.BackColor = Color.Red;
}))));
getDataDelegate(AlarmLevel.Level1, (resultList) => this.Invoke(new MethodInvoker(() =>
{
    if (resultList.Count == 0) return;
    foreach (AlarmResult result in resultList)
    {
        DataRow row = _dataTable.NewRow();
        row["报警级别"] = result.AlarmLevel;
        row["设备名称"] = result.DevName;
        row["报警描述"] = result.AlarmInfo;
        row["报警时间"] = result.AlarmTime;
        row["报警次数"] = result.AlarmCount;
        row["是否确认"] = result.IsConfirm;

        this._dataTable.Rows.Add(row);
    }
    this.ultraGrid.Refresh();
    this.BackColor = Color.Red;
})));

  还有个泛型委托Func,跟Action一样的。只不过它是有参有返回,大概,这个Action算是我日常项目中用于作为回调函数的最多的了

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值