如何返回带有我事先不知道的泛型参数的函数

本文关键字:不知道 泛型 函数 参数 有我 何返回 返回 | 更新日期: 2023-09-27 17:56:02

我想调用一个生成函数的函数,但我不知道类型参数,直到我像这样调用生成的函数:

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

在调用返回的函数之前,我不会知道 T 的类型。我想象这样的东西来生成函数,它将列表包装在闭包中,这样我就不必一直传递它。

Func<Func<MyObject,T>,ActionResult> OrderBy<T>(IEnumerable<MyObject> list) {
  Func<Func<MyObject,T>, ActionResult> f = orderBy => {
     return View(Request.QueryString["sortDir"] == "d"
        ? list.OrderBy<MyObject, T>(orderBy)
        : list.OrderByDescending<MyObject, T>(orderBy));
  };
  return f;
}

更新:

我知道有更好的方法可以做到这一点。我想知道如何将此列表包装在闭包中并返回一个具有我事先不知道的泛型类型的函数。例如,由于在不知道类型的情况下无法返回泛型类型函数,那么是否有某种类型可以替换它?

如何返回带有我事先不知道的泛型参数的函数

诀窍是确定您关心的两种类型共有的类型。 在这种情况下,它是 IComparable . 您正在排序,string s 和 int 都是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);
    }

这应该可以做到:

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