我正在使用C# 4.0。 我正在对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
将通过values["SomeColumn"]
访问"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"]
EvaluateExpressionUsingTheseValues
就values["SomeColumn"]()
了,相反。
很快,而第二个在构建字典方面没有每次迭代开销,但查找速度较慢。
哪个更好?
带有Dictionary<string, Func<object>>
的解决方案具有更多的开销。
原因是这些Func<object>
委托存在于需要分配的闭包对象上。这样做的成本可能比简单地索引到您的行中一次要高得多。
此外,无论如何,您以后可能都必须进行索引。然后,具有Func<object>
的解决方案将受益于EvaluateExpressionUsingTheseValues(values)
内部的缓存,以避免多次评估。但这就是第一个解决方案真正已经是。
我们无法为您回答这个问题。这取决于哪个更适合您的情况。
不过,就个人而言,我会选择第一种选择,因为它更容易破译。未来的开发人员在看到第二个选项时可能会爆炸,除非它有很好的文档记录!
我建议创建一个 Name/Value 类来反映 DataRow,创建大量 AnonymouseType 会降低性能,即使有相同的。
U 可能会对此进行基准测试:
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] };
}
}
}
一个重要因素是您最终实际需要的数据百分比是多少? 如果你知道你要对每一行使用每一列中的每个值(也许你正在把它全部打印到屏幕上,或者计算聚合数据(,那么你不妨马上计算实际值来填充你的字典。 如果您知道您只会稀疏地访问数据,从某些行中提取一小部分列,那么在某些情况下,使用延迟评估的第二种方法是值得的。
话虽如此,由于填充实际值本身并不是那么复杂,因此不太可能是那么大的胜利,因此更简单的(第一种(方法很可能是更好的选择。 当然,如果您知道您不需要尽早过滤掉某些行/列(理想情况下甚至不要从数据库中获取它们(将是最好的。