C# 将OrderBy lambda函数作为参数传递
假设我有一个模型名C# 将OrderBy lambda函数作为参数传递,c#,linq,lambda,C#,Linq,Lambda,假设我有一个模型名User,它有两个属性name和Age。我想知道lambda函数的类型,它接受用户并返回其中一个属性,以便lambda函数可以在OrderBy方法中使用 using System; using System.Linq; public class User { public string Name { get; set; } public int Age { get; set; } } public class MainClass { static v
User
,它有两个属性name
和Age
。我想知道lambda函数的类型,它接受用户
并返回其中一个属性,以便lambda函数可以在OrderBy
方法中使用
using System;
using System.Linq;
public class User {
public string Name { get; set; }
public int Age { get; set; }
}
public class MainClass {
static void Main() {
var users = new User[] {
new User { Name = "David", Age = 16 },
new User { Name = "Charlie", Age = 29 },
new User { Name = "Alice", Age = 15 },
new User { Name = "Deanna", Age = 27 },
}.AsQueryable();
Write(GetAdultsBy(users, u => u.Name));
Write(GetAdultsBy(users, u => u.Age));
}
private static IQueryable<User> GetAdultsBy(IQueryable<User> users, Func<User, object> order) {
return users
.Where(u => u.Age > 18)
.OrderBy(order); // FAIL in ORDER BY
}
private static void Write(IQueryable<User> query) {
var names = query.Select(u => u.Name);
Console.WriteLine(string.Join(", ", names));
}
}
使用系统;
使用System.Linq;
公共类用户{
公共字符串名称{get;set;}
公共整数{get;set;}
}
公共类主类{
静态void Main(){
var users=新用户[]{
新用户{Name=“David”,年龄=16},
新用户{Name=“Charlie”,年龄=29},
新用户{Name=“Alice”,年龄=15},
新用户{Name=“Deanna”,年龄=27},
}.AsQueryable();
写入(GetAdultsBy(users,u=>u.Name));
写入(GetAdultsBy(用户,u=>u.Age));
}
专用静态IQueryable GetAdultsBy(IQueryable用户,函数顺序){
返回用户
.其中(u=>u.年龄>18岁)
.OrderBy(order);//按顺序失败
}
私有静态无效写入(IQueryable查询){
var Name=query.Select(u=>u.Name);
Console.WriteLine(string.Join(“,”,name));
}
}
我在运行时遇到以下错误:
/tmp/997240133/main.cs(26,14):错误CS0266:无法将类型System.Linq.iorderenumerable'隐式转换为System.Linq.IQueryable'。存在显式转换(是否缺少强制转换?)
但是显式排序对于Write(users.OrderBy(u=>u.Age))来说效果很好代码>正如人们所料
那么Func order
参数的类型应该是什么呢?要使用IQueryable
,需要传递表达式树(expression
)
表达式树在运行时对lambda的内容进行编码,允许将其转换为SQL。要使用IQueryable
,您需要传递表达式树(expression
)
表达式树在运行时对lambda的内容进行编码,允许将其转换为SQL。您需要将私有静态IQueryable GetAdultsBy()
定义为一个通用函数,以匹配OrderBy的定义方式。具体而言:
private static IOrderedQueryable<User> GetAdultsBy<T>(
IQueryable<User> source,
Expression<Func<User, T>> order)
私有静态IOrderedQueryable GetAdultsBy(
可查询的来源,
表达顺序)
您需要将私有静态IQueryable GetAdultsBy()
定义为一个通用函数,以匹配OrderBy的定义方式。具体而言:
private static IOrderedQueryable<User> GetAdultsBy<T>(
IQueryable<User> source,
Expression<Func<User, T>> order)
私有静态IOrderedQueryable GetAdultsBy(
可查询的来源,
表达顺序)
您可以查看Queryable.OrderBy
的签名(在文档中或仅使用intellisense)以查看它接受的参数,因为您知道它不是Func
。您可以查看Queryable.OrderBy的签名(在文档中或仅使用intellisense)为了查看它接受什么参数,因为您知道它不是Func
。您能提供一个示例吗?我不明白。编辑答案。事实上,你得到的特殊例外是,根据SLaks的回答,你需要选择器的类型是Expression<>
。我认为这个不应该存在。即使删除它,我在u.Age
上也会得到一个错误,上面说:CS1061“User”不包含“Age”的定义,并且找不到接受“User”类型的第一个参数的扩展方法“Age”
没错,“this”是一个复制粘贴错误,额外的模板参数也是如此。我已经编辑了答案,请尝试使用该版本。需要注意的一点是,您需要使用表达式>
的唯一原因是,您已将函数定义为使用IQueryable
。但是,如果您只在内存阵列上工作过,那么这样做没有多大好处-您可以使用IEnumerable
。但是如果您确实计划在某个时候使用数据库,那么IQueryable
是正确的选择。您能提供一个示例吗?我不明白。编辑答案。事实上,你得到的特殊例外是,根据SLaks的回答,你需要选择器的类型是Expression<>
。我认为这个不应该存在。即使删除它,我在u.Age
上也会得到一个错误,上面说:CS1061“User”不包含“Age”的定义,并且找不到接受“User”类型的第一个参数的扩展方法“Age”
没错,“this”是一个复制粘贴错误,额外的模板参数也是如此。我已经编辑了答案,请尝试使用该版本。需要注意的一点是,您需要使用表达式>
的唯一原因是,您已将函数定义为使用IQueryable
。但是,如果您只在内存阵列上工作过,那么这样做没有多大好处-您可以使用IEnumerable
。但是如果您确实计划在某个时候使用数据库,那么IQueryable
是正确的选择。您能提供一个示例吗?我不明白。我认为这是正确的方法,但是在这种情况下,…
是什么?@styfle:Func
(参数和返回类型)的类型参数。查看OrderBy()
的签名。您能提供一个示例吗?我不明白。我认为这是正确的方法,但是在这种情况下,…
是什么?@styfle:Func
(参数和返回类型)的类型参数。查看OrderBy()
的签名。