优化For循环结果?

时间:2015-10-21 05:43:08

标签: c# for-loop optimization

我目前正在使用此代码检查DataReader是否存在列:

df2
 [1] "/Desktop"                                              
 [2] "/Desktop/all"                    
 [3] "/Programms"          

我重复使用这段代码,因此它会持续运行For循环。

无论如何我可以优化这个吗?例如,如果列不存在,则表示结果对于所有内容都相同,我不必再次遍历所有内容。如果它存在,我知道它是存在的,不需要再次循环。

谢谢!

3 个答案:

答案 0 :(得分:3)

该功能的代码很好。您应该检查您的调用代码,例如,不要在DataReader或DataTable的每次迭代中调用它。

在迭代所有记录之前,您应该调用此方法一次。如果表或游标的每一行都没有相同的列,那么机会很小。

答案 1 :(得分:3)

主要问题在于调用代码...但是您可以通过更改创建方法并返回HashSet<string>来避免多次调用该方法:

public static class DataRecordExtensions
{
    public static ISet<string> GetFieldNames(this IDataRecord dr, StringComparer comparer)
    {
        var sequence = Enumerable.Range(0, dr.FieldCount)
                                 .Select(i => dr.GetName(i));
        return new HashSet<string>(sequence, comparer);
    }
}

然后,您可以使用第一条记录调用该方法,并将StringComparer.InvariantCultureIgnoreCase作为比较器传入,然后您将获得ISet<string>,您可以便宜地测试它是否包含特定记录字段名称。

尴尬的部分可能只召唤一次。您可能需要以下内容:

ISet<string> fields = null;
while (reader.Read())
{
    var record = ...;
    if (fields == null)
    {
        fields = record.GetFieldNames(StringComparer.InvariantCultureIgnoreCase);
    }
    // Use fields and record here
}

如果您还需要字段 number ,您可能还需要考虑返回Dictionary<string, int>而不是ISet<string>

答案 2 :(得分:0)

一个选项是将列名存储在字典中,然后可以使用它来快速查找列名。

鉴于您正在使用扩展方法,您需要使用ConditionalWeakTable来存储和检索给定数据读取器的字典。检查它是否存在,如果不是缓存并使用这种方法存储它。

请记住,第一次调用它时,它可能会比现在慢,因为您可以将方法短路(因为您需要将所有列名称缓存)。如果这是一个问题,您可以使用混合方法进行缓存,直到您找到退出后的列,下次如果您在缓存中找不到该列,请继续搜索并添加缓存任何新列,一旦找到您之后的列(或者到达列的末尾),就会立即退出。

我应该说这三种方法中哪一种最好(你目前加上这两种方法)在很大程度上取决于:

  1. 您为给定数据阅读器调用此方法的次数
  2. 数据阅读器中有多少列,
  3. 您搜索的列和订单
  4. 例如,如果您的阅读器中有100列并且搜索位置97的列,然后是98然后是99,那么我上面的第一种方法可能是最好的(首次使用时全部缓存)。但是,如果你搜索了位置1和100之后的列,那么混合方法之间的一些可能会更好。只需在任何地方搜索数据阅读器,您最好采用当前的方法!