使用Func<T1, T2, TResult> 委托返回匿名对象
Func<T1, T2, TResult> 委托
封装一个具有两个参数并返回 TResult 参数指定的类型值的方法。
语法
public delegate TResult Func<in T1, in T2, out TResult>( T1 arg1, T2 arg2 )
类型参数 in T1 此委托封装的方法的第一个参数类型。 该类型参数是逆变。即可以使用指定的类型或派生程度更低的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。 in T2 此委托封装的方法的第二个参数类型。 out TResult 此委托封装的方法的返回值类型。 该类型参数是协变。即可以使用指定的类型或派生程度更高的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。 参数 arg1类型:T1 此委托封装的方法的第一个参数。 arg2类型:T2 此委托封装的方法的第二个参数。 返回值 类型:TResult 此委托封装的方法的返回值。
备注
可以使用此委托表示一种能以参数形式传递的方法,而不用显式声明自定义委托。封装的方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有两个均通过值传递给它的参数,并且必须返回值。
若要引用具有两个参数并返回 void 的方法(或者要在 Visual Basic 中引用被声明为 Sub 而不是被声明为 Function 的方法),请改用泛型 Action<T1, T2> 委托。
在使用 Func<T1, T2, TResult> 委托时,不必显式定义一个封装具有两个参数的方法的委托。例如,以下代码显式声明了一个名为 ExtractMethod 的委托,并将对 ExtractWords 方法的引用分配给其委托实例。
示例
下面的示例演示如何声明和使用 Func<T1, T2, TResult> 委托。此示例声明一个 Func<T1, T2, TResult> 变量,并将其分配给一个采用 String 值和 Int32 值作为参数的 lambda 表达式。如果 String 参数的长度等于 Int32 参数的值,则此 lambda 表达式将返回 true。随后在查询中使用封装此方法的委托来筛选字符串数组中的字符串。
using System; using System.Collections.Generic; using System.Linq; public class Func3Example { public static void Main() { Func<String, int, bool> predicate = (str, index) => str.Length == index; String[] words = { "orange", "apple", "Article", "elephant", "star", "and" }; IEnumerable<String> aWords = words.Where(predicate).Select(str => str); foreach (String word in aWords) Console.WriteLine(word); } }
了解完这些以后,我们来看看它的应用。
不知道童鞋们有没有遇到这样的问题,在读取数据访问层中数据集合时,发现该方法需要返回的结果中包括对象及其外键对象时,又不想添加一个实体类来封装它,那么有什么别的好办法吗?也许您会选择用动态对象(dynamic关键字),不错,这个这确实可以解决这个问题,但是有一个弊端,且不论动态对象在运行时编译,在编写程序时,它存在一个很不方便的体验,它不能点(.)出它的属性,不免产生意外的拼写错误或是寻找-复制-黏贴的麻烦。
那么怎么办呢?我们可以利用Func<T1, T2, TResult> 委托来帮助我们实现。
public IEnumerable<TResult> GetAllUser<TResult>(Func<User, Person, TResult> itemFactory) { var results = from u in User join p in Person on u.Id equals p.uId select new { User = u, Person = p }; IList<TResult> resultItems = new List<TResult>(); foreach (var item in results.ToList()) { resultItems.Add(itemFactory(item.User, item.Person)); } return resultItems; }
var query = userDao.GetAllUser((u, p) => { return new { u.Id, u.LoginName, pId = p.Id, p.Name }; });
此外,当然也可以自定义更多的委托,这里笔者就不详细介绍了,读者可自行尝试。
哈哈,这样是否有帮到您呢?本人文笔粗糙简陋,请多多大虾们指教!