C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托是保存对某个方法引用的一种引用类型变量。
若要引用的方法,具有两个参数没有返回值,使用Action
若要引用的方法,具有两个参数并返回一个值,使用泛型Func
一、使用delegate定义没有返回值的委托:
using System;
using System.IO;
delegate void ConcatStrings(string string1, string string2);
public class TestDelegate
{
public static void Main()
{
string message1 = "The first line of a message.";
string message2 = "The second line of a message.";
ConcatStrings concat;
if (Environment.GetCommandLineArgs().Length > 1)
concat = WriteToFile;
else
concat = WriteToConsole;
concat(message1, message2);
}
private static void WriteToConsole(string string1, string string2)
{
Console.WriteLine("{0}\n{1}", string1, string2);
}
private static void WriteToFile(string string1, string string2)
{
StreamWriter writer = null;
try
{
writer = new StreamWriter(Environment.GetCommandLineArgs()[1], false);
writer.WriteLine("{0}\n{1}", string1, string2);
}
catch
{
Console.WriteLine("File write operation failed...");
}
finally
{
if (writer != null) writer.Close();
}
}
}
使用Action
using System;
using System.IO;
public class TestAction2
{
public static void Main()
{
string message1 = "The first line of a message.";
string message2 = "The second line of a message.";
Action concat;
if (Environment.GetCommandLineArgs().Length > 1)
concat = WriteToFile;
else
concat = WriteToConsole;
concat(message1, message2);
}
private static void WriteToConsole(string string1, string string2)
{
Console.WriteLine("{0}\n{1}", string1, string2);
}
private static void WriteToFile(string string1, string string2)
{
StreamWriter writer = null;
try
{
writer = new StreamWriter(Environment.GetCommandLineArgs()[1], false);
writer.WriteLine("{0}\n{1}", string1, string2);
}
catch
{
Console.WriteLine("File write operation failed...");
}
finally
{
if (writer != null) writer.Close();
}
}
}
二、使用delegate定义有返回值的委托:
using System;
delegate string[] ExtractMethod(string stringToManipulate, int maximum);
public class DelegateExample
{
public static void Main()
{
ExtractMethod extractMeth = ExtractWords;
string title = "The Scarlet Letter";
foreach (string word in extractMeth(title, 5))
Console.WriteLine(word);
}
private static string[] ExtractWords(string phrase, int limit)
{
char[] delimiters = new char[] {' '};
if (limit > 0)
return phrase.Split(delimiters, limit);
else
return phrase.Split(delimiters);
}
}
使用泛型Func
using System;
public class GenericFunc
{
public static void Main()
{
Func extractMethod = ExtractWords;
string title = "The Scarlet Letter";
foreach (string word in extractMethod(title, 5))
Console.WriteLine(word);
}
private static string[] ExtractWords(string phrase, int limit)
{
char[] delimiters = new char[] {' '};
if (limit > 0)
return phrase.Split(delimiters, limit);
else
return phrase.Split(delimiters);
}
}
使用Action
Predicate
Predicate泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。
先来看一下Array.FindAll
// 摘要:
// 检索与指定谓词定义的条件匹配的所有元素。
//
// 参数:
// array:
// 要搜索的从零开始的一维 System.Array。
//
// match:
// System.Predicate`1,定义要搜索元素的条件。
//
// 类型参数:
// T:
// 数组元素的类型。
//
// 返回结果:
// 如果找到一个 System.Array,其中所有元素均与指定谓词定义的条件匹配,
// 则为该数组;否则为一个空 System.Array。
//
// 异常:
// T:System.ArgumentNullException:
// array 为 null。 - 或 - match 为 null。
public static T[] FindAll(T[] array, Predicate match);
FindAll两个参数第一个就是数组(字符串数组,int数组等等),第二个就是委托Predicate有一个参数。
第一种方式:通过一个lambda表达式传递参数
string[] arrayString = new string[]{"One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"};
string[] arrayResult = Array.FindAll(arrayString, (c) => c.Length > 3);
第二种方式:通过委托进行传递方法的方式
public void PredicateArrayTest()
{
string[] arrayString = new string[]{"One","Two","Three","Four","Fice","Six",
"Seven","Eight","Nine","Ten"};
string[] arrayResult = Array.FindAll(arrayString, (c) => c.Length > 3);
string[] arrayResultMethod = Array.FindAll(arrayString, GetString);
}
private bool GetString(string item)
{
if (item.Length > 3)
{
return true;
}
return false;
}
第三种方式:通过匿名代理
string[] arrayResultDelegate = Array.FindAll(arrayString, delegate(string c) { return c.Length > 3; });
对List的实现其实和Array的实现原理几乎完全一样。