C# 如何返回一个带有我事先不知道的泛型参数的函数?
我想调用一个生成函数的函数,但在调用生成的函数之前,我不知道类型参数,如下所示:C# 如何返回一个带有我事先不知道的泛型参数的函数?,c#,generics,closures,C#,Generics,Closures,我想调用一个生成函数的函数,但在调用生成的函数之前,我不知道类型参数,如下所示: ActionResult Foo() { IEnumerable<MyObject> list = GetList(); var orderBy = OrderBy(list); // <-- HOW DO I WRITE OR DO THIS; switch(Request.QueryString["sortBy"]) { case "Name": retur
ActionResult Foo() {
IEnumerable<MyObject> list = GetList();
var orderBy = OrderBy(list); // <-- HOW DO I WRITE OR DO THIS;
switch(Request.QueryString["sortBy"]) {
case "Name":
return orderBy<string>(o => o.Name); // <-- SO I CAN MAKE THIS CALL
case "TrackingNumber":
return orderBy<int>(o => o.TrackingNumber); // <-- AND THIS ONE
default:
return View(list);
}
}
ActionResult Foo(){
IEnumerable list=GetList();
var orderBy=orderBy(list);//o.Name);//o.TrackingNumber);//{
返回视图(Request.QueryString[“sortDir”]=“d”
?列表。订购人(订购人)
:list.OrderByDescending(orderBy));
};
返回f;
}
更新:
我知道有更好的方法。我想知道如何将这个列表包装成一个闭包,并返回一个具有泛型类型的函数。例如,由于我无法在不知道类型的情况下返回泛型类型函数,是否有某种类型可以替换它?这应该可以:
ActionResult Foo() {
IEnumerable<MyObject> list = GetList();
switch(Request.QueryString["sortBy"]) {
case "Name":
return OrderBy(list, o => o.Name); // <-- SO I CAN MAKE THIS CALL
case "TrackingNumber":
return OrderBy(list, o => o.TrackingNumber); // <-- AND THIS ONE
default:
return View(list);
}
}
ActionResult OrderBy<T>(IEnumerable<MyObject> list, Func<MyObject, T> orderBy) {
return View(Request.QueryString["sortDir"] == "d"
? list.OrderBy<MyObject, T>(orderBy)
: list.OrderByDescending<MyObject, T>(orderBy));
}
ActionResult Foo(){
IEnumerable list=GetList();
开关(Request.QueryString[“sortBy”]){
案例“名称”:
return OrderBy(list,o=>o.Name);///o.TrackingNumber);//诀窍是识别两种类型共同关心的类型。在这种情况下,它是IComparable
。您正在排序,string
s和int
s都是IComparable
您还使问题变得比需要的复杂得多。您不需要太多返回Func
的Func
。您可以简化
另外,您也不希望ASP.NET MVC类渗透到整个应用程序中。请将这些内容保存在控制器中,并让执行实际工作的代码获取参数,以便它不知道它正在ASP.NET MVC或web中运行,并且可以进行单元测试
public static IEnumerable<MyObject> GetSortedList(string sortBy, bool sortAscending)
{
IEnumerable<MyObject> list = GetList();
Func<MyObject, IComparable> keySelector;
switch (sortBy)
{
case "Name":
keySelector = o => o.Name;
break;
case "TrackingNumber":
keySelector = o => o.TracingNumber;
break;
default:
return list;
}
return sortAscending
? list.OrderBy(keySelector)
: list.OrderByDescending(keySelector);
}
公共静态IEnumerable GetSortedList(字符串排序,布尔排序)
{
IEnumerable list=GetList();
Func键选择器;
开关(sortBy)
{
案例“名称”:
keySelector=o=>o.名称;
打破
案例“TrackingNumber”:
keySelector=o=>o.TracingNumber;
打破
违约:
退货清单;
}
返回排序
?列表。订购人(按键选择器)
:list.OrderByDescending(键选择器);
}
Name和Tracking number是特定于UI的。这就是它们位于控制器中的原因。我的服务层对这些项目一无所知。我发布的所有代码都在控制器中。我也知道Request.QueryString的性能较差,但我一直在维护最初在1.0中编写的现有MVC应用程序,而这正是我所没有的o目前与一起工作。虽然你的答案实际上没有回答我的具体问题,但这是一种更好的实现方法。我只是想看看我是否能够完成这项技术。在f#中,部分函数应用程序并不少见。我一直在试着看看我每天在工作中编写的c#可以应用什么。Re:你的更新。请参阅下面是我的答案。如果你提供一个Func
你所说的类型是自动确定的。对于o=>o.Name
它是string
,对于o=>o.TrackingNumber
它是int
等等……你通过选择一个类属性作为排序键来隐式指定该类型。你的答案是d它不会将列表包装成闭包,而是将其传递给方法,这违背了我问题的目的。
public static IEnumerable<MyObject> GetSortedList(string sortBy, bool sortAscending)
{
IEnumerable<MyObject> list = GetList();
Func<MyObject, IComparable> keySelector;
switch (sortBy)
{
case "Name":
keySelector = o => o.Name;
break;
case "TrackingNumber":
keySelector = o => o.TracingNumber;
break;
default:
return list;
}
return sortAscending
? list.OrderBy(keySelector)
: list.OrderByDescending(keySelector);
}