【问题标题】:Problem with Generic Linq OrderBy function通用 Linq OrderBy 函数的问题
【发布时间】:2009-09-10 19:30:35
【问题描述】:

我在一篇帖子中看到了以下函数,它允许使用通用表达式对数据进行排序:

public static IOrderedQueryable<T> OrderBy<T, TKey>(
  this IQueryable<T> source, Expression<Func<T, TKey>> func, bool isDescending) {
  return isDescending ? source.OrderByDescending(func) : source.OrderBy(func);
}

当我尝试使用此函数时,我收到一条错误消息,提示“找不到类型或命名空间名称“TKey”(您是否缺少 using 指令或程序集引用?)”。我在这里做一些愚蠢的事情但我想不通。

编辑:

在做了更多研究之后,我认为我的问题在于构建我传递给它的表达式。是否可以构建一个可以包含不同类型的表达式?假设我的数据集有一个字符串、一个 int 和一个 bool,我想使用上面的通用函数对任何项目进行排序。我该怎么做?

我现在有这个工作:

if (IsString)
{
   Expression<Func<T, string>> expString = ...;
   // call orderBy with expString
}
else if (IsInt)
{
   Expression<Func<T, int>> expInt;
   // call orderBy w/ expInt
}
:

我想要类似的东西:

Expression<Func<T, {something generic!}>> exp;
if (IsString)
    exp = ...;
else if (IsInt)
    exp = ...;
:
// call orderBy with exp

【问题讨论】:

  • 这看起来不错。你是如何使用这种方法的?您是否将其添加到静态类中?

标签: c# linq lambda


【解决方案1】:

一个快速观察:您实际上并不需要使用 lambda 表达式 (Expression&lt;Func&lt;T,TKey&gt;&gt;)。一个简单的委托 (Func&lt;T,TKey&gt;) 就可以了。

也就是说,我认为您可能正在寻找的答案是:

Func<T,IComparable> func = null;
if (IsString)
    func = (T a) => a.SomeStringValue;
else if (IsInt)
    func = (T a) => a.SomeIntValue;
// call orderBy with exp

【讨论】:

  • 这似乎是我正在寻找的。但是,我玩了一下它并无法编译它。当我尝试将 func 传递给 OrderBy 函数时,编译器会抱怨。如果可行,您的方法会稍微干净一些,但不幸的是,我现在不能花更多的时间。
  • 如果你有时间,请告诉我你看到的编译器错误是什么。
  • 我终于回到了这个话题。我认为问题在于,在我的自定义 orderBy 函数中,我调用了不带 Func 参数的 ThenBy - 它需要 lambda 表达式。
  • 您可以创建一个 ThenBy 重载,然后使用 Func。仅在需要以某种方式分析 lambda 表达式时才应使用它们。如果您只需要执行表达式,那么您应该使用委托。
【解决方案2】:

我的目标是消除大量重复代码。除了处理升序/降序之外,我的“OrderBy”函数还可以处理其他一些常见的逻辑。假设原始帖子中的函数定义,可以简单地这样做:

if ( {need to sort by integer})
    query = OrderBy(objectT, a => a.myIntegerField, asc);
else if ( {need to sort by string})
    query = OrderBy(objectT, a=> a.myStringField, asc);
:

【讨论】:

    【解决方案3】:

    表达式只能有一种类型;我在这里的首选答案是:

    IQueryable<T> query = ...
    if({case 1}) {
        query = query.OrderBy(x=>x.SomeValue);
    } else if({case 2}) {
        query = query.OrderBy(x=>x.SomeOtherValue);
    } ...
    

    但是,如果您想做一些更灵活的事情,您可能需要进入自定义Expression 写作;某事more like this

    【讨论】:

    • 这就是我最初拥有的,但由于我有很多字段并且需要处理升序/降序排序,我最终得到了大量的“重复”代码。我发布的答案似乎运作良好。
    【解决方案4】:

    【讨论】:

      【解决方案5】:

      看看this answer

      我的通用排序处理程序是:

      • “dgvProcessList”是我的dataGridView
      • “进程”是我绑定到它的对象
      • “e”是我的 DataGridViewCellMouseEventArgs

                    PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();
                if (isSortedASC == true)
                    dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderByDescending(x => column.GetValue(x, null)).ToList();
                else
                    dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderBy(x => column.GetValue(x, null)).ToList();
        
                isSortedASC = !isSortedASC;
                dgvProcessList.ClearSelection();
        

      干杯

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-04
        相关资源
        最近更新 更多