将固定大小的数组添加到IEnumerable

时间:2013-09-04 08:08:01

标签: c# arrays enumerable

此方法获得:

IEnumerable<object[]> - 其中每个数组都是固定大小(它代表关系 数据结构)。

DataEnumerable.Column[] - 一些元数据列,它们通常对所有行都具有相同的值。

预期结果:

每个“行”应为每个列获取值(因此数据结构保持关系)。

    private IEnumerable<object[]> BindExtraColumns(IEnumerable<object[]> baseData, int dataSize, DataEnumerable.Column[] columnsToAdd)
    {
        int extraColumnsLength = columnsToAdd.Length;
        object[] row = new object[dataSize + extraColumnsLength];

        string columnName;
        int rowNumberColumnIndex = -1;

        for (int i = 0; i < extraColumnsLength; i++)
        {
            //Assign values that doesn't change between lines..
            // Assign rowNumberColumnIndex if row number column exists
        }

        //Assign values that change here, since we currently support only row number
        // i'ts not generic enough        
        if (rowNumberColumnIndex != -1)
        {
            int rowNumber = 1;

            foreach (var baseRow in baseData)
            {
                row[rowNumberColumnIndex] = rowNumber;

                Array.Copy(baseRow, 0, row, extraColumnsLength, dataSize);

                yield return row;

                rowNumber++;
            }
        }
        else
        {
            foreach (var baseRow in baseData)
            {
                Array.Copy(baseRow, 0, row, extraColumnsLength, dataSize);

                yield return row;
            }
        }
    }

这个方法可以从具有相对较大数据集的数百个线程中调用 这里的性能至关重要,我试图尽可能地创建最小的新对象。

请注意 - 这是一种私有方法,它使用 ONLY BY DataReader读取每一行,并在读取下一行之前立即将其传递给另一个

那么 - 这里的复制数组是否会以某种方式进行优化,我应该使用(小心)内存来增强这里的内容吗?

由于

1 个答案:

答案 0 :(得分:5)

您的代码从根本上被打破了。您只是每次都返回对同一个数组的引用,这意味着除非调用者立即使用每个项中的数据,否则它会有效地丢失。例如,假设我使用:

List<object[]> rows = BindExtraColumns(data, size, toAdd).ToList();

然后,当我遍历行时​​,我会在每一行中找到相同的数据。这真的不是一个好的经历。

我认为为每次迭代创建一个新数组会使更多更有意义。是的,这是使用了很多额外的内存 - 但它并没有给呼叫者带来惊喜。

如果您真的不想这样做,我建议您更改方法,以便调用者必须传入Action<object[]>以在每一行执行,并记录条件是如果调用者存在对数组的引用,他们可能会对结果感到惊讶。

您显然非常关注性能,但如果您的数据来自数据库,我希望数组创建/复制性能无关紧要。您应该编写首先运行的最简单(和最可靠)代码,然后对其进行基准测试以查看它是否运行良好。除非你有证据,你需要做出这个令人惊讶的设计选择,感觉就像你过早地进行优化一样。

编辑:现在我们知道它是一个私有方法在一个特定的地方使用,我仍然避免这种重用。它简直是脆弱的。我真的会改为传递Action<object[]>或者只是每次都将数据复制到一个新数组。如果没有强有力的证据这是一个瓶颈,我当然不会保留当前的方法:正如我之前所说,我希望数据库通信更加重要。像这样在你的代码中留下时间炸弹很少能很好地解决。

如果你真的,想要继续这样做,你应该强烈地记录非常,给出严重的警告,结果是非惯用的。

就是否有更多优化而言,你可以做到 - 嗯......一种替代方案是避免首先使用单个阵列。您可以创建一个类,该类包含对两个数组(当前基本行和固定数据)的引用,并公开一个索引器,该索引器根据请求的索引从一个数组或另一个数组返回值。我们不知道你在做什么数据(“把它传递给另一个数组”并不是真的意味着什么)所以我们不知道这是否可行,但它会有效可以在没有奇怪行为的情况下实施。