为了调用FindAll方法

时间:2021-07-26 08:24:30

匿名要领是C# 2.0的语言新特性。首先看个最简单的例子:

class Program { static void Main(string[] args) { List<string> names = new List<string>(); names.Add("Sunny Chen"); names.Add("Kitty Wang"); names.Add("Sunny Crystal"); List<string> found = names.FindAll( new Predicate<string>(NameMatches)); if (found != null) { foreach (string str in found) Console.WriteLine(str); } } static bool NameMatches(string name) { return name.StartsWith("sunny", StringComparison.OrdinalIgnoreCase); } }

这段代码在开始的时候初始化了一个字符串列表(string list),然后通过列表的FindAll要领来查找以“sunny”起始的字符串,最后将所查找到的所有功效输出。

我们需要着重介绍List<T>的FindAll要领。这个要领是一个参数为Predicate<T>类型、返回值为List<T>类型的函数。注意,Predicate<T>是一个泛型委托,它指代这样一些函数:这些函数仅有一个T类型的参数,并且返回值是布尔类型。通过reflector等工具,我们可以看到Predicate<T>的界说如下:

public delegate bool Predicate<T>(T obj);

至此我们也几多能够猜到FindAll要领的具体实现。即针对List<T>中的每个元素,挪用Predicate<T>所指代的函数,如果函数返回为true,则将其插手新建的列表中。遍历完所有的元素后,将新建的列表返回给挪用者。如下:

public List<T> FindAll<T>(Predicate<T> match) { List<T> ret = new List<T>(); foreach (T elem in items) { if (match(elem)) ret.Add(elem); } return ret; }

因此,针对上面的例子,要挪用FindAll要领,我们必需先界说一个参数为string类型,返回值为布尔类型的函数,在这个函数中,对参数进行条件判断,如果切合条件(也就是以“sunny”作为起始字符串),,那么就返回true,否则返回false。最后再将这个函数作为参数通报给FindAll。于是也就得到了最上面的代码。

在上面的例子中,为了挪用FindAll要领,我们不得不新界说一个函数,其实这个函数除了FindAll要领要用外,另外处所都几乎很少使用到它,你还不得不给它起个名字。如果措施中有多处需要挪用FindAll要领,或者类似的情况,那么整个措施也就会呈现一多量“只有一个处所使用”的函数,使得代码难于阅读和维护。

由于存在这样的问题,C# 2.0引入了匿名要领。开发人员在实现要领的时候,只需要给出要领的参数列表(甚至也可以不给)以及要领具体实现,而不需要关心要领的返回值,更不必给要领起名字。最关键的是,只在需要的处所界说匿名要领,保证了代码的简洁。

匿名要领只在需要的处所界说,界说的时候,使用delegate关键字,后接参数列表,然后跟上用一对花括号包孕起来的函数体即可。上面的代码可以重组成下面的形式:

class Program { static void Main(string[] args) { List<string> names = new List<string>(); names.Add("Sunny Chen"); names.Add("Kitty Wang"); names.Add("Sunny Crystal"); List<string> found = names.FindAll( delegate(string name) { return name.StartsWith("sunny", StringComparison.OrdinalIgnoreCase); }); if (found != null) { foreach (string str in found) Console.WriteLine(str); } } //static bool NameMatches(string name) //{ // return name.StartsWith("sunny", // StringComparison.OrdinalIgnoreCase); //} }

此时,我们完全不需要NameMatches要领了,直接将匿名要领作为参数通报给FindAll要领。其实匿名要领自己还是有名字的,只是我们并不关心它究竟该取什么名字,因而.NET帮我们随便取了个名字罢了。

匿名要领在C#中应用十分广泛,因为委托作为函数参数是件非常泛泛的工作。在界说简单的事件措置惩罚惩罚过程时,我们同样可以使用匿名要领。好比:

ServiceHost host = new ServiceHost(typeof(FileTransferImpl)); host.Opened += delegate(object sender, EventArgs e) { Console.WriteLine("Service Opened."); };

匿名要领可以很便利地使用本地变量,这与单独界说的定名要领对比,能够简化编程。好比上文的例子中,假如Main函数里面界说了一个整型本地变量(局部变量)number,那么可以在delegate (string name)这一匿名要领界说中使用number变量。

上文提到,在界说匿名要领的时候,连参数列表都可以省略。因为编译器可以按照委托的签名来确定函数的签名,然后只要再给函数起个名字就可以了。下面的代码演示了这种使用方法:

delegate void IntDelegate(int x); // 带参数的界说方法 IntDelegate d2 = delegate(int p) { Console.WriteLine(p); }; // 不带参数的界说方法(固然也没带返回值) IntDelegate d3 = delegate { Console.WriteLine("Hello."); };

在使用不带参数和返回值的匿名要领界说时,需要注意以下两点: