委托简介
本文只介绍怎么用,至于在什么情况下用,只能靠经验积累,望各位日后用心感悟哦
- Delegate使用
- Action使用
- Func使用
- Predicate使用
- 匿名委托
- 异步委托(进阶)
温馨提示:相关解释都在每一行代码注释中 ~
Delegate使用
public delegate void CalculatorDelegate(int a, int b);
public delegate int CalculatorDelegate1(int a, int b);
public class maintest
{
/// <summary>
/// Delegate程序入口
/// </summary>
/// <param name="action"></param>
/// <param name="a"></param>
/// <param name="b"></param>
public void Run()
{
int a = 2;
int b = 3;
#region 简单委托
CalculatorDelegate calculatorDelegate = new CalculatorDelegate(CalculatorAddImple);
if (calculatorDelegate != default(CalculatorDelegate))
{
calculatorDelegate(a, b);
}
#endregion
#region 多播委托
CalculatorDelegate multiCalculatorDelegate = default(CalculatorDelegate);
//加法计算器
multiCalculatorDelegate += new CalculatorDelegate(CalculatorAddImple);
//加法计算器 + 减法计算器
multiCalculatorDelegate += new CalculatorDelegate(CalculatorSubImple);
//加法计算器 + 减法计算器 + 乘法计算器
multiCalculatorDelegate += new CalculatorDelegate(CalculatorChengImple);
//加法计算器 + 减法计算器 + 乘法计算器 + 除法计算器
multiCalculatorDelegate += new CalculatorDelegate(CalculatorChuImple);
if (multiCalculatorDelegate != default(CalculatorDelegate))
{
multiCalculatorDelegate(a, b);
}
#endregion
#region 带返回值类型的委托
#region 简单委托
CalculatorDelegate1 calculatorDelegate1 = new CalculatorDelegate1(CalculatorAddImple1);
if (calculatorDelegate1 != default(CalculatorDelegate1))
{
calculatorDelegate1(a, b);
}
#endregion
#region 多播委托
CalculatorDelegate1 multiCalculatorDelegate1 = default(CalculatorDelegate1);
//加法计算器
multiCalculatorDelegate1 += new CalculatorDelegate1(CalculatorAddImple1);
//加法计算器 + 减法计算器
multiCalculatorDelegate1 += new CalculatorDelegate1(CalculatorSubImple1);
//加法计算器 + 减法计算器 + 乘法计算器
multiCalculatorDelegate1 += new CalculatorDelegate1(CalculatorChengImple1);
//加法计算器 + 减法计算器 + 乘法计算器 + 除法计算器
multiCalculatorDelegate1 += new CalculatorDelegate1(CalculatorChuImple1);
if (multiCalculatorDelegate1 != default(CalculatorDelegate1))
{
//委托有返回值,就会只返回最后一个实现方法的返回值
var yy = multiCalculatorDelegate1(a, b);
//只要委托不等于空,反复删除同一个委托,不会报错并且不会执行
multiCalculatorDelegate1 -= new CalculatorDelegate1(CalculatorSubImple1);
multiCalculatorDelegate1 -= new CalculatorDelegate1(CalculatorSubImple1);
var yy2 = multiCalculatorDelegate1(a, b);
//委托清空,才会报错
multiCalculatorDelegate1 -= new CalculatorDelegate1(CalculatorSubImple1);
multiCalculatorDelegate1 -= new CalculatorDelegate1(CalculatorAddImple1);
multiCalculatorDelegate1 -= new CalculatorDelegate1(CalculatorChengImple1);
multiCalculatorDelegate1 -= new CalculatorDelegate1(CalculatorChuImple1);
var yy3 = multiCalculatorDelegate1(a, b);
}
#endregion
#endregion
#region dynamicinvoke
//动态传入参数:
//编译时:参数数量不匹配,参数类型不匹配,参数顺序不一致,都不会报错,但是运行时会报错
CalculatorDelegate1 dynamicDelegate = new CalculatorDelegate1(CalculatorAddImple1);
dynamicDelegate.DynamicInvoke(a, b);
#endregion
}
public void CalculatorAddImple(int a, int b)
{
Console.WriteLine("加法:" + (a + b));
}
public void CalculatorSubImple(int a, int b)
{
Console.WriteLine("减法:" + (a - b));
}
public void CalculatorChengImple(int a, int b)
{
Console.WriteLine("乘法:" + (a * b));
}
public void CalculatorChuImple(int a, int b)
{
Console.WriteLine("除法(整除):" + (a / b));
}
public int CalculatorAddImple1(int a, int b)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i=0;i<10000;i++)
{
for (int j = 0; j < 100000; j++)
{
Console.WriteLine("CalculatorAddImple1 method working");
}
}
stopwatch.Stop();
Console.WriteLine($"waste time:{stopwatch.ElapsedMilliseconds}");
Console.WriteLine("加法:" + (a + b));
return 1;
}
public int CalculatorSubImple1(int a, int b)
{
Console.WriteLine("减法:" + (a - b));
return 1;
}
public int CalculatorChengImple1(int a, int b)
{
Console.WriteLine("乘法:" + (a * b));
return 1;
}
public int CalculatorChuImple1(int a, int b)
{
Console.WriteLine("除法(整除):" + (a / b));
return 4;
}
}
Action使用
该委托没有返回类型
public void ActionTestImple(int a)
{
Console.WriteLine("Action 委托实现方法");
}
/// <summary>
/// Action委托测试入口
/// </summary>
/// <returns></returns>
public void ActionTest()
{
Action<int> action = new Action<int>(ActionTestImple);
//该委托没有返回类型
action(1);
}
Func使用
有返回值的委托
public bool FuncTestImple(int a)
{
return false;
}
/// <summary>
/// Func委托测试入口
/// Func<int, bool> - int:参数 bool:返回值
/// Func<int> - int:返回值
/// </summary>
/// <param name="calculatorAction"></param>
public void FuncTest(CalculatorDelegate calculatorAction)
{
var array = new int[5] { 1, 5, 9, 4, 6 };
//有返回值的函数运用
Func<int, bool> predicateNormal = new Func<int, bool>(FuncTestImple);
array.FirstOrDefault(predicateNormal);
}
Predicate使用
该委托只返回bool类型
/// <summary>
/// Predicate委托测试入口
/// </summary>
/// <returns></returns>
public void PredicateTest()
{
Predicate<int> predicate = new Predicate<int>(PredicateTestImple);
//该委托只返回bool类型
bool flag=predicate(1);
}
匿名委托
public bool FuncTestImple(int a)
{
return false;
}
/// <summary>
/// 匿名委托测试入口
/// Func<int, bool> - int:参数 bool:返回值
/// Func<int> - int:返回值
/// </summary>
/// <param name="calculatorAction"></param>
public void FuncTest(CalculatorDelegate calculatorAction)
{
var array = new int[5] { 1, 5, 9, 4, 6 };
//有返回值的函数运用
Func<int, bool> predicateNormal = new Func<int, bool>(FuncTestImple);
array.FirstOrDefault(predicateNormal);
//有返回值的匿名函数运用
// ----------------方法1
Func<int, bool> predicate = delegate (int sth)
{
return false;
};
Func<int, bool> predicate1 = (int sth)=>
{
return false;
};
Func<int, bool> predicate2 = (it) =>
{
return false;
};
array.FirstOrDefault(predicate);
array.FirstOrDefault(predicate1);
array.FirstOrDefault(predicate2);
// ----------------方法2
array.FirstOrDefault(delegate (int sth)
{
return false;
});
array.FirstOrDefault( (int sth)=>
{
return false;
});
array.FirstOrDefault((it) =>
{
return false;
});
}
委托进阶-异步委托
有两种方式供选择:
方式1:
可以结合业务决定什么时候主动调用EndInvoke获取结果
/// <summary>
/// 程序入口
/// </summary>
/// <param name="action"></param>
/// <param name="a"></param>
/// <param name="b"></param>
public void Run()
{
int a = 2;
int b = 3;
#region 委托进阶-异步委托
CalculatorDelegate1 myDelegate = new CalculatorDelegate1(CalculatorAddImple1);
IAsyncResult asyncResult = myDelegate.BeginInvoke(a, b, null, null);
//调用EndInvoke,当前线程会等待结果生成,不会执行之后的代码,所以自己决定什么时候调用该方法。
var value = myDelegate.EndInvoke(asyncResult);
}
/// <summary>
/// 回调函数,当该异步实现方法执行完毕之后,由该方法进行EndInvoke取结果并结束该线程。
/// </summary>
/// <typeparam name="TInput"></typeparam>
/// <param name="asyncResult"></param>
private void Completed<TInput>(IAsyncResult asyncResult) where TInput : Point
{
AsyncResult result = (AsyncResult)asyncResult;
//beginInvoke 取最后一个参数
var param = result.AsyncState as Point;
//取beginInvoke的delegate对象
var myDelegate = result.AsyncDelegate as CalculatorDelegate1;
//取Invoke的最终结果
var value=myDelegate.EndInvoke(asyncResult);
}
方式2(推荐):
在进程结束之前,如果还有异步结果没有完成,让当前进程等待其全部完成,调用如下:GlobalAsyncResultCache.WaitAllFinished();。
/// <summary>
/// 程序入口
/// </summary>
/// <param name="action"></param>
/// <param name="a"></param>
/// <param name="b"></param>
public void Run()
{
int a = 2;
int b = 3;
#region 委托进阶-异步委托
CalculatorDelegate1 myDelegate = new CalculatorDelegate1(CalculatorAddImple1);
IAsyncResult asyncResult = myDelegate.BeginInvoke(a, b, Completed<Point>, new Point() { x = 1, y = 1 });
GlobalAsyncResultCache.AddRuningResult(asyncResult);
}
/// <summary>
/// 回调函数,当该异步实现方法执行完毕之后,由该方法进行EndInvoke取结果并结束该线程。
/// </summary>
/// <typeparam name="TInput"></typeparam>
/// <param name="asyncResult"></param>
private void Completed<TInput>(IAsyncResult asyncResult) where TInput : Point
{
AsyncResult result = (AsyncResult)asyncResult;
//beginInvoke 取最后一个参数
var param = result.AsyncState as Point;
//取beginInvoke的delegate对象
var myDelegate = result.AsyncDelegate as CalculatorDelegate1;
//取Invoke的最终结果
var value=myDelegate.EndInvoke(asyncResult);
}
/// <summary>
/// 进程内异步结果缓存
/// </summary>
public class GlobalAsyncResultCache
{
private static IList<IAsyncResult> asyncResults = new List<IAsyncResult>();
public static void AddRuningResult(IAsyncResult result)
{
asyncResults.Add(result);
}
public static void WaitAllFinished()
{
foreach (IAsyncResult asyncResult in asyncResults)
{
WaitOne(asyncResult);
}
}
private static void WaitOne(IAsyncResult asyncResult)
{
while (!asyncResult.IsCompleted)
{
System.Threading.Thread.Sleep(1);
}
}
}