在这种情况下使用哪种更好的数据结构:Dictionary <string,func <object =“”>&gt;或字典<string,object =“”>?</string,> </string,>

时间:2012-07-24 16:29:46

标签: c# algorithm data-structures dictionary

我正在使用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将通过"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"]中的EvaluateExpressionUsingTheseValues只会是values["SomeColumn"]()

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

哪个更好?

4 个答案:

答案 0 :(得分:1)

我认为我们不能为您解答这个问题。这取决于你的情况哪个更好。

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

答案 1 :(得分:1)

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

原因是这些Func<object>委托生活在需要分配的闭包对象上。这个成本可能远远高于简单地索引到您的行一次。

此外,您可能还需要稍后进行索引编制。然后,Func<object>的解决方案将受益于EvaluateExpressionUsingTheseValues(values)内的缓存,以避免多次评估。但这就是第一个解决方案真正存在的问题。

答案 2 :(得分: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] };
        }
    }
}

答案 3 :(得分:1)

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

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