Predicate 泛型委托

  表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。

看看下面它的定义:


// Summary:

    //     Represents the method that defines a set of criteria and determines whether

    //     the specified object meets those criteria.

    //

// Parameters:

    //   obj:

    //     The object to compare against the criteria defined within the method represented

    //     by this delegate.

    //

// Type parameters:

    //   T:

    //     The type of the object to compare.

    //

// Returns:

    //     true if obj meets the criteria defined within the method represented by this

    //     delegate; otherwise, false.


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

类型参数介绍:

   T: 要比较的对象的类型。

   obj: 要按照由此委托表示的方法中定义的条件进行比较的对象。

   返回值:如果 obj 符合由此委托表示的方法中定义的条件,则为 true;否则为 false

看下面代码:




泛型委托 Predicate/Func/Action_泛型


public class GenericDelegateDemo

    {

        List<String> listString = new List<String>()

        {

            "One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"

        };


        String[] arrayString = new String[]

        {

             "One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"

        };


        public String[] GetFirstStringFromArray()

        {

            return Array.FindAll(arrayString, (c) => { return c.Length <=3; });

        }


        public List<String> GetFirstStringFromList()

        {

            return listString.FindAll((c) => { return c.Length <=3; });

        }


        public String[] GetFirstStringFromArray_1()

        {

            return Array.FindAll(arrayString, GetString);

        }


        public List<String> GetFirstStringFromList_1()

        {

            return listString.FindAll(GetString);

        }


        private bool GetString(String str)

        {

            if (str.Length <=3)

                return true;

            else

                return false;

        }

    }


泛型委托 Predicate/Func/Action_泛型


 


(1)首先,上面以 数组和泛型List 两个集合作为演示对象,并构建集合。

(2)接着,两者同时使用各自 所有的 FindALL方法,参见如下定义:

    Array : public T[] FindAll<T>(T[] array, Predicate<T> match);

    List:public List<T> FindAll(Predicate<T> match);

    注意的是,两处的FindAll 均采用了Predicate (泛型委托)作为参数的类型。

(3)接着,使用两者方式展现 对Predicate 的使用:

    第一种:  (c) => { return c.Length <= 3; };

    第二种: GetString(String str)。

这两者在语法上明显不同,但是实际是做相同的事情,第一种是使用Lambda表达式构建的语句,关于Lambda这里不做详述,请参见笔者C#3.0特性相关文章。

补充的是你也可以这样写,



 delegate(String c){return c.Length<=3;}


 

  作为 Predicate定义的参数

完整代码: 



XX.FindAll(delegate(String c) { return c.Length <=3; }); 


 

这应该称为匿名代理了。

其他使用到Predicate 有

  Array.Find , Array.FindAll , Array.Exists , Array.FindLast , Array.FindIndex ..... 

  List<T>.Find , List<T>.FindAll , List<T>.Exists , List<T>.FindLast , List<T>.FindIndex ..... 

延伸:

  除了上面提到的外,你完全可以使用Predicate 定义新的方法,来加强自己代码。




泛型委托 Predicate/Func/Action_泛型


public class GenericDelegateDemo

{

    List<String> listString = new List<String>()

    {

        "One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"

    };


    public String GetStringList(Predicate<String> p)

    {

        foreach(string item in listString)

        {

            if (p(item))

                return item;

        }

        return null;

    }


    public bool ExistString()

    {

        string str = GetStringList((c) => { return c.Length <= 3 && c.Contains('S'); });

        if (str == null)

            return false;

        else

            return true;

    }

}


泛型委托 Predicate/Func/Action_泛型


 

同样解决了上面的问题,这里罗嗦了只是为说明Predicate的用法而已。

对于Predicate的应用当然这不是什么新鲜事情,今天细细思味一番,觉得C# 真是一门优雅的语言。

以供初学者参考。

笔者本想对以下几种泛型委托一一做些介绍和总结的,在理解Predicate的过程中,发现只要理解了泛型、委托和匿名代理,

当然你晓得Lambda表达式更好,就完全可以在适当的时候灵活应用他们了。也就是说,只是定义不同的delegate而已,

一是 你可以自己定义这样的delegate,再行使用;

二是 你需要知道象Predicate、Func、Action这样的已有好的delegate是如何定义的。或者使用的时候适当查阅下MSDN即可。

如:

Func():封装一个不具有参数但却返回 TResult 参数指定的类型值的方法。

Func(T1, T2, TResult):封装一个具有两个参数并返回 TResult 参数指定的类型值的方法,没有T2就是封装一个具有参数并....。

Action() Action(T1) Action(T2) : 封装一个方法,该方法指定数量的参数(如()无参数,(T1)一个参数,以此类推)并且不返回值。这个和Func有相似处,但无返回值而已。


提醒大家的注意的是:

  x=>x+x;

    与

  X=> {return x+x;} 是等价的。

针对解释我又结合MVC做了下练习。

 1、结构

泛型委托 Predicate/Func/Action_c#_05 

2、如图分别在Controller 下建立PredicateController.cs;Views下建立Predicate文件夹,然后在其下建立index (View)


泛型委托 Predicate/Func/Action_c#_06


泛型委托 Predicate/Func/Action_泛型


using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;


namespace PredicatePractice.Controllers

{

    public class PredicateController : Controller

    {

        //

        // GET: /Predicate/

        

        public ActionResult Index()

        {

            List<string> StrList = new List<string>() { 

            "One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"

            };


            string[] arrayList = new string[] {

            "One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"

            };

            //返回arrayList中长度小于3的单词数组(string[])

            string[] NewArray = Array.FindAll(arrayList, c => c.Length < 4);


            //返回StrList中中长度小于3的单词数组(List<string>)

            List<string> NewList = StrList.FindAll(c => c.Length < 4);


            //利用CheckStr方法(泛型委托)来进行筛选

            string[] NewArrayUseCheckFunc = Array.FindAll(arrayList, CheckStr);


            //利用CheckStr方法(泛型委托)来进行筛选

            List<string> NewListUseCheckPredicate = StrList.FindAll(CheckStr);


            ViewData["NewArray"] = NewArray;

            ViewData["NewList"] = NewList;

            ViewData["NewArrayUseCheckFunc"] = NewArrayUseCheckFunc;

            ViewData["NewListUseCheckPredicate"] = NewListUseCheckPredicate;

            return View();

        }


        /// <summary>

        /// 检查字符串S长度 是否小于4

        /// </summary>

        /// <param name="S"></param>

        /// <returns></returns>

        private bool CheckStr(string S)

        {

            if (S.Length < 4)

                return true;

            else

                return false;

        }


    }

}


泛型委托 Predicate/Func/Action_泛型


 

 

 


泛型委托 Predicate/Func/Action_c#_06


泛型委托 Predicate/Func/Action_泛型


<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>


<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">

    index

</asp:Content>


<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">


    <h2>Pradicatepractice

    <br />

        数组{"One","Two","Three","Four","Fice","Six","Seven","Eight","Nine","Ten"}<br />

        --------------Begin--------------<br />

        <font color="red"><b>string[] NewArray = Array.FindAll(arrayList, c => c.Length < 3);</b></font><br />

        结果:

        <% IList<string> NewArray = (ViewData["NewArray"] as IEnumerable<string>).ToList<string>(); %>

        <%= Html.Display("<br/>") %>

        <% for (int i = 0; i < NewArray.Count; i++) %>

        <% { %>

        <%= Html.Label(NewArray[i].ToString())%>

        <% } %>

        <br />

        ------------------------------<br />

        <font color="red"><b>List< string > NewList = StrList.FindAll(c => c.Length < 3);</b></font><br />

        结果:

        <% IList<string> NewList = (ViewData["NewList"] as IEnumerable<string>).ToList<string>(); %>

        <% for (int j = 0; j < NewList.Count; j++) %>

        <% { %>

        <%= Html.Label(NewList[j].ToString())%>

        <% } %>

        <br />

        ------------------------------<br />

        <font color="red"><b>Lstring[] NewArrayUseCheckFunc = Array.FindAll(arrayList, CheckStr);</b></font><br />

        结果:

        <% IList<string> NewArrayUseCheckFunc = (ViewData["NewArrayUseCheckFunc"] as IEnumerable<string>).ToList<string>(); %>

        <% for (int k = 0; k < NewArrayUseCheckFunc.Count; k++) %>

        <% { %>

        <%= Html.Label(NewArrayUseCheckFunc[k].ToString())%>

        <% } %>

        <br />

        ------------------------------<br />

        <font color="red"><b>List< string > NewListUseCheckPredicate = StrList.FindAll(CheckStr);</b></font><br />

        结果:

        <% IList<string> NewListUseCheckPredicate = (ViewData["NewListUseCheckPredicate"] as IEnumerable<string>).ToList<string>(); %>

        <% for (int l = 0; l < NewListUseCheckPredicate.Count; l++) %>

        <% { %>

        <%= Html.Label(NewListUseCheckPredicate[l].ToString())%>

        <% } %>

        <br />

        ---------------End---------------<br />

    </h2>


</asp:Content>


泛型委托 Predicate/Func/Action_泛型


 

 效果如图:

泛型委托 Predicate/Func/Action_封装_12