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。
看下面代码:
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
;
}
}
(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 定义新的方法,来加强自己代码。
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的用法而已。
对于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、结构
2、如图分别在Controller 下建立PredicateController.cs;Views下建立Predicate文件夹,然后在其下建立index (View)
PredicateController.cs
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
;
}
}
}
index.aspx
<%
@ 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
>
效果如图:
很清楚了。^_^