C# 如何提高c语言上Casting对象的性能#

C# 如何提高c语言上Casting对象的性能#,c#,.net,C#,.net,我正在使用下面的函数将行转换为列,但是我只能在1秒内旋转4行。这对我的应用程序来说太慢了 public static DataTable ToPivotTable<T, TColumn, TRow, TData>( this IEnumerable<T> source, Func<T, TColumn> columnSelector, Expression<Func<T, TRow>> rowSelector, Func<IEn

我正在使用下面的函数将行转换为列,但是我只能在1秒内旋转4行。这对我的应用程序来说太慢了

 public static DataTable ToPivotTable<T, TColumn, TRow, TData>(
this IEnumerable<T> source,
Func<T, TColumn> columnSelector,
Expression<Func<T, TRow>> rowSelector,
Func<IEnumerable<T>, TData> dataSelector)
    {
        DataTable table = new DataTable();
        var rowName = ((MemberExpression)rowSelector.Body).Member.Name;
        table.Columns.Add(new DataColumn(rowName.ToString(), typeof(DateTime)));
        var columns = source.Select(columnSelector).Distinct();



foreach (var column in columns)
            table.Columns.Add(new DataColumn(column.ToString(), typeof(double)));

    var rows = source.GroupBy(rowSelector.Compile())
                     .Select(rowGroup => new
                     {
                         Key = rowGroup.Key,
                         Values = columns.GroupJoin(
                             rowGroup,
                             c => c,
                             r => columnSelector(r),
                             (c, columnGroup) => dataSelector(columnGroup))
                     });

    foreach (var row in rows)
    {
        var dataRow = table.NewRow();
        var items = row.Values.Cast<object>().ToList();
        items.Insert(0, row.Key);
        dataRow.ItemArray = items.ToArray();
        table.Rows.Add(dataRow);
    }

    return table;
}
公共静态数据表ToPivotTable(
这是一个数不清的来源,
Func列选择器,
表达式行选择器,
Func数据选择器)
{
DataTable=新的DataTable();
var rowName=((MemberExpression)rowSelector.Body).Member.Name;
table.Columns.Add(新的数据列(rowName.ToString(),typeof(DateTime));
var columns=source.Select(columnSelector).Distinct();
foreach(列中的var列)
table.Columns.Add(新数据列(column.ToString(),typeof(double));
var rows=source.GroupBy(rowSelector.Compile())
.选择(行组=>新建)
{
Key=rowGroup.Key,
Values=columns.GroupJoin(
rowGroup,
c=>c,
r=>列选择器(r),
(c,columnGroup)=>dataSelector(columnGroup))
});
foreach(行中的变量行)
{
var dataRow=table.NewRow();
var items=row.Values.Cast().ToList();
项目。插入(0,行。键);
dataRow.ItemArray=items.ToArray();
table.Rows.Add(dataRow);
}
返回表;
}
我意识到以下每行需要250毫秒才能完成。这是主要问题

var items = row.Values.Cast<object>().ToList();
var items=row.Values.Cast().ToList();

如何提高该行的性能?

此代码效率低下:

foreach (var row in rows)
{
    var dataRow = table.NewRow();
    var items = row.Values.Cast<object>().ToList();
    items.Insert(0, row.Key);
    dataRow.ItemArray = items.ToArray();
    table.Rows.Add(dataRow);
}
foreach(行中的变量行)
{
var dataRow=table.NewRow();
var items=row.Values.Cast().ToList();
项目。插入(0,行。键);
dataRow.ItemArray=items.ToArray();
table.Rows.Add(dataRow);
}
您正在创建一个列表(一个O(N)操作),然后在其开始处插入一个项(另一个O(N)操作),然后将其转换为一个数组(另一个O(N)操作)

您可以通过以下方式对此进行改进:

foreach (var row in rows)
{
    var dataRow = table.NewRow();
    var items   = row.Values.Cast<object>();
    items = new[] {row.Key}.Concat(items);
    dataRow.ItemArray = items.ToArray();
    table.Rows.Add(dataRow);
}
foreach(行中的变量行)
{
var dataRow=table.NewRow();
var items=row.Values.Cast();
items=new[]{row.Key}.Concat(items);
dataRow.ItemArray=items.ToArray();
table.Rows.Add(dataRow);
}
这意味着只有一个O(N)操作—调用
items.ToArray()


(如果无法编译,我不知道这是否完全正确-您可能需要
items=new object[]{row.Key}.Concat(items);

这部分代码对我来说太通用了:

Values = columns.GroupJoin(
                         rowGroup,
                         c => c,
                         r => columnSelector(r),
                         (c, columnGroup) => dataSelector(columnGroup))
实际上是一个独立的
IEnumerable
,您正在为每个
行组
计算它-您应该以最有用的形式预先计算它(但是
列表
不会是一个坏的开始)

使用
GroupJoin
选择每个可能出现的
columnSelector(r)
值的
dataSelector
似乎有些过分

如果你做了呢

var columns = source.Select(columnSelector).Distinct().Orderby(c => c.ToString()).ToList();
强制对
ItemArray
执行显式(字母顺序)顺序

那你就可以了

Values = rowGroup.GroupBy(r => columnSelector(r))
                 .Orderby(rg => rg.Key)
                 .Select(rg => dataSelector(rg))

还有@MatthewWatson的建议。

谢谢,不过现在“dataRow.ItemArray=items.ToArray();”这行花了250毫秒。@S.Doe您是否需要将其转换为
对象
?如果省略
.Cast
,需要多长时间?如果仍然需要约250毫秒,那么您几乎无能为力。(因此,如果使用time
row.Values.ToArray()
,需要多长时间?)。另外,您是如何计时的?我怀疑Linq将花费时间来创建
序列的每个元素。它对每个元素执行
GroupJoin()
。我只想将行转换为列。我不知道我是否需要施法反对。是否可以使用无对象?我正在逐行使用调试,它显示了前一行的计时响应时间。@S.Doe我不认为现在是强制转换,我认为是对每一行执行的GroupJoin()。但是,我应该如何更改以下以foreach循环开始的部分;foreach(var row in rows){Nice函数。比我写的更通用。
var columns = source.Select(columnSelector).Distinct().Orderby(c => c.ToString()).ToList();
Values = rowGroup.GroupBy(r => columnSelector(r))
                 .Orderby(rg => rg.Key)
                 .Select(rg => dataSelector(rg))