前言
C#用了4年了,之前一直对“委托”这个概念不是很理解,前几天突然就豁然开朗了。所以在这里记一下,希望这不仅是对自己成长的记录,也能对小伙伴们有所帮助。
分析
C#委托,可以看成是一种函数指针,它将会非常有用当你想将某个方法作为参数传入另外一个方法时(我也想吐槽一下这样写语序有些偏英文化,但是貌似这样写会使主体表达更连贯?)。
委托可以使用delegate实现,但本文所讨论的是委托的另外两种实现方式:Action和Func。相比delegate关键字,使用Action和Func会使代码更简洁。Action和Func两者的区别在于Action没有返回值,而Func有返回值。
开始
本文将通过一个例子来介绍Action和Func的概念及使用方法。
打开VS2017,新建控制台应用,取名为ActionFuncTest,确定。
将Program.cs的代码替换为下面代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ActionFuncTest
{
class Program
{
static int num = 0;
static void Main(string[] args)
{
StartYourShow();
Console.Read();
}
static void StartYourShow()
{
while (num < 5)
{
num += 1;
Console.WriteLine("show");
}
Console.WriteLine("ShowEnd");
}
}
}
F5运行,你将会看到的结果如下图所示:
我们分析一下StartYourShow这个方法的组成,它可以看做事由3部分组成的:
-
不终止条件(num<5)。或者说终止条件(num>=5)
-
循环事件(num+=1;Console.WriteLine(“show”);)
-
终止后事件(Console.WriteLine(“ShowEnd”)?
从某种意义上来说, StartYourShow 这个方法,把以上三个组成元素都给写死了。如果现在提出需求,我们需要一个类似 StartYourShow ,但可以为它指定以上三个组成元素的方法,该怎么做呢?
很简单,只要把Program.cs代码替换为如下代码即可:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ActionFuncTest
{
class Program
{
static int num = 0;
static void Main(string[] args)
{
StartYourShow(CanEnd, Method, EndMethod);
Console.Read();
}
static void StartYourShow(Func<bool> CanEnd, Action Method, Action EndMethod)
{
while (!CanEnd()) Method();
EndMethod();
}
static bool CanEnd()
{
if (num >= 5) return true;
else return false;
}
static void Method()
{
num += 1;
Console.WriteLine("show");
}
static void EndMethod()
{
Console.WriteLine("ShowEnd");
}
}
}
功能是实现了,但是代码却无比繁琐。但值得开心的是,上面代码可以简化为如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ActionFuncTest
{
class Program
{
static int num = 0;
static void Main(string[] args)
{
Func<bool> CanEnd = () => num >= 5;
Action Method = () => { num += 1; Console.WriteLine("show"); };
Action EndMethod = () => Console.WriteLine("ShowEnd");
StartYourShow(CanEnd, Method, EndMethod);
Console.Read();
}
static void StartYourShow(Func<bool> CanEnd, Action Method, Action EndMethod)
{
while (!CanEnd()) Method();
EndMethod();
}
}
}
甚至简化为以下形式:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ActionFuncTest
{
class Program
{
static int num = 0;
static void Main(string[] args)
{
StartYourShow(
() => num >= 5,
() => { num += 1; Console.WriteLine("show"); },
() => Console.WriteLine("ShowEnd"));
Console.Read();
}
static void StartYourShow(Func<bool> CanEnd, Action Method, Action EndMethod)
{
while (!CanEnd()) Method();
EndMethod();
}
}
}
到这里,关于Action和Func的基本使用,相信大家也会豁然开朗了吧。
前面说过,Action是不带返回值的,而Func是带返回值的(上面的Func表示该Func返回值为bool类型);它们还有一个相同点,就是都可以带一个或多个参数。
为了探究带参数的Action和Func,可以将Program.cs代码替换为以下代码;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ActionFuncTest
{
class Program
{
static int num = 0;
static void Main(string[] args)
{
StartYourShow(
(n) => n >= 5,
(s) => { num += 1; Console.WriteLine(s); },
(s1,s2) => Console.WriteLine(s1+s2));
Console.Read();
}
static void StartYourShow(Func<int,bool> CanEnd, Action<string> Method, Action<string,string> EndMethod)
{
while (!CanEnd(num))
Method(DateTime.Now.TimeOfDay.ToString());
EndMethod("Show","End");
}
}
}
值得注意的一点是,上面的代码中,在调用 Func<int,bool> CanEnd 时,只需要传入一个int型参数即可,它将会返回一个bool类型的值。即Func尖括号内最后一个类型代表该Func的返回类型。
结束
这篇博客总结了C#的Action和Func的使用,希望对小伙伴们有帮助。
若有不足请指正,感谢。