C# 委托: delegate、Action、Func

委托

委托是一中引用类型,表示对具有特定参数列表和返回类型的方法的引用.同其他引用类型一样,都是对某个对象的引用,只不过普通的引用对象是变量类型,委托的引用对象为方法.在实例化委托时可以与兼容的方法相关联,进而可以通过委托调用方法.

作用:委托的作用是将方法作为参数传递给其他方法.事件处理程序就是通过委托调用方法.

声明委托

1
public delegate <委托类型> 委托名([参数]);

例如

1
pubic delegate void Action(int x, int y);

委托拥有的属性

  • 委托会同时封装对象实例和方法.
  • 允许把一个方法作为参数传递给另一个方法, 可用于定义回调函数.
  • 方法不必与委托类型完全匹配(类型的协变与逆变).
  • Lambda 表达式可编译为委托类型

案例

使用委托定义回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public delegate void Callback(string msg);

public static void Main(string[] args)
{
var doSomething = new Callback(OutMsg);
DoSomething("实现回调", doSomething);
}

public static void OutMsg(string msg)
{
Console.WriteLine(msg);
}

public static void DoSomething(string msg, Callback callback)
{
callback(msg);
}

使用Lambda定义回调函数

1
2
3
4
5
6
7
8
9
10
11
12
public void _Main()
{
DoSomething("实现回调", (msg) =>
{
Console.WriteLine(msg);
});
}

public static void DoSomething(string msg, Callback callback)
{
callback(msg);
}

效果与上述相同

Action

Action是定义在System命名空间下的委托,其封装一个方法,该方法没有返回值, 在 .NET Framework 4.0 及以后的版本中共预定义了17个Action委托.

1
2
3
4
5
6
7
public delegate void Action();
public delegate void Action<in T>(T obj);
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);

...

public delegate void Action<in T1, in T2, ... , in T16>(T1 arg1, T2 arg2, ... ,T16 arg16);
1
2
3
4
5
6
7
8
9
10
11
12
public void _Main()
{
DoSomething("实现回调", (msg) =>
{
Console.WriteLine(msg);
});
}

public static void DoSomething(string msg, Action<string> callback)
{
callback(msg);
}

在 .NET Framework 4.0 之后的版本,提供了最多16个参数的Action封装, 3.5 最多4个参数.

Func

Func是定义在System命名空间下的委托,其封装一个方法,该方法有返回值,TResult 为其返回值类型, 在 .NET Framework 4.0 及以后的版本中共预定义了17个Func委托.

1
2
3
4
5
6
7
public delegate TResult Func<TResult>();
public delegate TResult Func<in T, out TResult>(T obj);
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

...

public delegate TResult Func<in T1, in T2, ... , in T16, out TResult>(T1 arg1, T2 arg2, ... ,T16 arg16);

总结

ActionFunc 本质是委托,其存在的目的是为了不用每次使用委托都去重新定义,而每次重新定义都是一模一样的,无非就是参数的个数和类型不同,预定义的ActionFunc 提供了最多16个参数的委托,这在使用中完全足够.

  1. Action 用于没有返回值的方法(参数可以根据自己情况进行传递)
  2. Func 恰恰相反用于有返回值的方法(同样参数根据自己情况情况)
  3. 记住无返回就用 Action,有返回就用 Func.