C#中Predicate<T>与Func<T, bool>泛型委托的用法实例

 更新时间:2014年09月06日 11:22:10   投稿:shichen2014  
这篇文章主要介绍了C#中Predicate<T>与Func<T, bool>泛型委托的用法,指出了其用法中的误区及易错点,有助于更好的理解泛型委托的用法,需要的朋友可以参考下

本文以实例形式分析了C#中Predicate<T>与Func<T, bool>泛型委托的用法,分享给大家供大家参考之用。具体如下:

先来看看下面的例子:

static void Main(string[] args)  
{  
  List<string> l = new List<string>();  
  l.Add("a");  
  l.Add("b");  
  l.Add("s");  
  l.Add("t");  
 
  if (l.Exists(s => s.Equals("s")))  
  {  
    string str = l.First(s => s.Equals("s"));  
    Console.WriteLine(str);  
  }  
  else 
    Console.WriteLine("Not found");  
}  

非常简单,就是先判断字符串列表l中是否有s字符串,如果有,则取之并显示出来。从代码中可以看到,l.Exists方法和l.First方法所使用的参数是相同的,但事实是否真是如此?

事实上,List<T>.Exists和List<T>.First的参数分别使用了不同的委托:
Predicate<T>和Func<T, bool>。从函数的签名上看,两者没有区别,都是指代的参数类型为T,返回值为bool的函数,但毕竟两者属于不同的委托类型,因此,下面的代码显然是无法编译通过的:

static void Main(string[] args)  
{  
  List<string> l = new List<string>();  
  l.Add("a");  
  l.Add("b");  
  l.Add("s");  
  l.Add("t");  
  Func<string, bool> p = s => s.Equals("s");  
  if (l.Exists(p))  
  {  
    string str = l.First(p);  
    Console.WriteLine(str);  
  }  
  else 
    Console.WriteLine("Not found");  
}  

然而,由于Predicate<T>和Func<T, bool>的确指代的是同一类具有相同签名的函数,而我们往往又不希望将匿名方法的方法体重复地写两次以分别赋予Predicate<T>和Func<T, bool>泛型委托,因此,我们可以自己写一个扩展方法,扩展Func<T, bool>类型以使其能够很方便的转换成Predicate<T>类型:

public static class Extensions  
{  
  public static Predicate<T> ToPredicate<T> (this Func<T, bool> source)
  {  
    Predicate<T> result = new Predicate<T>(source);  
    return result;  
  }  
}  

在引入了这个扩展方法之后,我们的代码就可以写成下面的形式:

static void Main(string[] args)  
{  
  List<string> l = new List<string>();  
  l.Add("a");  
  l.Add("b");  
  l.Add("s");  
  l.Add("t");  
  Func<string, bool> p = s => s.Equals("s");  
  if (l.Exists(p.ToPredicate()))  
  {  
    string str = l.First(p);  
    Console.WriteLine(str);  
  }  
  else 
    Console.WriteLine("Not found");  
}  

说实话不知为何MS要用这样两种完全不同的泛型委托来实现Exists和First方法,这使得某些情况下代码变得相对复杂,甚至容易出错。我想大概是为了语义清晰的缘故,Exists不过是做判断,因此需要用断言表达式,而在做First操作的时候,则更多的意义上是在迭代地调用指定的方法。学无止境,有待继续探索。

希望本文所述对大家的C#程序设计有所帮助

相关文章

  • c# 进程之间的线程同步

    c# 进程之间的线程同步

    这篇文章主要介绍了c# 进程之间的线程同步,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下
    2020-10-10
  • Unity UGUI实现滑动翻页直接跳转页数

    Unity UGUI实现滑动翻页直接跳转页数

    这篇文章主要为大家详细介绍了Unity UGUI实现滑动翻页,直接跳转页数,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 详细介绍C#之文件校验工具的开发及问题

    详细介绍C#之文件校验工具的开发及问题

    目前校验文件使用最多的是MD值和SHA值,不外乎有些使用CRC,前段时间微软发布了VisualStudio正式版,win镜像,微软官方给出的校验方式都是校验文件的SHA值。下面详细介绍C#之文件校验工具的开发及问题,需要的朋友可以参考下
    2015-07-07
  • Unity实现批量Build打包详解

    Unity实现批量Build打包详解

    一般来讲如果项目是PC或Android、IOS端不会有批量Build打包这样的需求,但如果项目是WebGL端可能会遇到这样的需求。本文主要为大家介绍Unity中如何实现Build批量打包的,需要的朋友可以参考一下
    2021-12-12
  • C#中增强类功能的几种方式详解

    C#中增强类功能的几种方式详解

    这篇文章主要给大家介绍了关于C#中增强类功能的几种方式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2018-12-12
  • 将c#编写的程序打包成应用程序的实现步骤分享(安装,卸载) 图文

    将c#编写的程序打包成应用程序的实现步骤分享(安装,卸载) 图文

    时常会写用c#一些程序,但如何将他们和photoshop一样的大型软件打成一个压缩包,以便于发布.
    2011-12-12
  • C# WPF使用GDI实现截屏功能

    C# WPF使用GDI实现截屏功能

    这篇文章主要为大家详细介绍了C# WPF如何使用GDI实现截屏功能,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • C#生成不重复随机字符串类

    C#生成不重复随机字符串类

    这篇文章主要介绍了C#生成不重复随机字符串类,涉及C#随机数与字符串的操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • C#实现简单播放mp3的方法

    C#实现简单播放mp3的方法

    这篇文章主要介绍了C#实现简单播放mp3的方法,涉及C#播放多媒体文件的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • 详解C# Socket简单例子(服务器与客户端通信)

    详解C# Socket简单例子(服务器与客户端通信)

    这篇文章主要介绍了详解C# Socket简单例子(服务器与客户端通信) ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-12-12

最新评论