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);
    }