2

我正在使用 C# 4.0。我正在对 a 的每一行执行一堆计算System.Data.DataTable。我不能给出实际的代码,但它归结为这样的东西:

DataTable table = GetMyTableFromSomewhere();
string[] columnNames = table.Columns.Cast<DataColumn>().Select(c => c.ColumnName).ToArray();
foreach (var row in table.Rows.Cast<DataRow>())
{
    Dictionary<string, object> values = columnNames.ToDictionary(c => c, c => row[c]);
    EvaluateExpressionUsingTheseValues(values);
}

然后EvaluateExpressionUsingTheseValues"SomeColumn"通过values["SomeColumn"].

我的想法是在循环内创建字典是资源密集型的。因此,这样的事情可能更省时:

DataTable table = GetMyTableFromSomewhere();
int rowIndex = -1;
var values = table.Columns.Cast<DataColumn>().Select(c => new
{ 
    Key = c.ColumnName, 
    Value = new Func<object>(() => table.Rows[rowIndex][c.ColumnName])
}).ToDictionary(kv => kv.Key, kv => kv.Value);

for (rowIndex = 0; rowIndex < table.Rows.Count; rowIndex++)
{
    EvaluateExpressionUsingTheseValues(values);
}

然后values["SomeColumn"]inEvaluateExpressionUsingTheseValues将只是values["SomeColumn"](),而不是。

我认为第一个构建字典的每次迭代开销很大,但查找速度很快,而第二个在构建字典方面没有每次迭代开销,但查找速度较慢。

哪个更好?

4

4 回答 4

1

我不认为我们可以为你回答这个问题。这取决于哪个更适合您的情况。

不过,就我个人而言,我会选择第一个选项,因为它更容易破译。未来开发人员的大脑可能会在看到第二个选项时爆炸,除非它有很好的文档记录!

于 2012-07-24T16:37:33.353 回答
1

您会发现解决方案Dictionary<string, Func<object>>具有更多开销。

原因是这些Func<object>委托存在于需要分配的闭包对象上。这样做的成本可能比简单地索引到您的行一次要高得多。

此外,无论如何,您可能必须稍后再进行索引。然后,该解决方案Func<object>将受益于内部缓存EvaluateExpressionUsingTheseValues(values)以避免多次评估。但这确实是第一个解决方案。

于 2012-07-24T16:37:40.953 回答
1

我建议创建一个 Name/Value 类来反映 DataRow,创建大量 AnonymouseType 会降低性能,即使它们相同。

你可以用这个做一个基准:

public class DataTableHelper
{
    class RowItem
    {
        public string Name { get; set; }
        public object Value { get; set; }
    }
    public IEnumerable<RowItem> Convert(System.Data.DataTable table)
    {
        string[] columns = (from System.Data.DataColumn n in table.Columns select n.ColumnName).ToArray();

        foreach (System.Data.DataRow row in table.Rows)
        {
            foreach (string column in columns)
                yield return new RowItem() { Name = column, Value = row[column] };
        }
    }
}
于 2012-07-24T17:00:34.700 回答
1

一个重要因素是您最终实际需要的数据百分比是多少?如果您知道要为每一行使用每一列中的每个值(也许您将其全部打印到屏幕上,或者计算聚合数据),那么您也可以直接计算实际值填充您的字典。如果您知道您只会稀疏地访问数据,仅从某些行中提取一小部分列,那么在某些情况下,可能,使用第二种延迟评估的方法是值得的。

话虽如此,由于填充实际值本质上并不是那么复杂,因此不太可能取得那么大的胜利,因此更简单的(第一种)方法很可能是更好的选择。当然,如果您知道您不需要某些行/列尽早将它们过滤掉(理想情况下甚至不需要从数据库中获取它们)将是最好的。

于 2012-07-24T17:00:39.710 回答