2

私は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"]inEvaluateExpressionUsingTheseValuesvalues["SomeColumn"]()代わりに , になります。

1 つ目は、辞書を作成するための反復ごとのオーバーヘッドが大きいが、ルックアップが高速であることがわかります。一方、2 つ目は、辞書を作成するという点で反復ごとのオーバーヘッドはありませんが、ルックアップは遅くなります。

どちらが良いですか?

4

4 に答える 4

1

DataRow を反映する Name/Value クラスを作成することをお勧めします。多数の 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] };
        }
    }
}
于 2012-07-24T17:00:34.700 に答える
1

重要な要素の 1 つは、そのデータの何パーセントが実際に必要になるかということです。各行のすべての列のすべての値を使用することがわかっている場合 (すべてを画面に出力するか、集計データを計算している可能性があります)、悪いところから実際の値を計算することもできます。辞書に入力します。データにまばらにアクセスするだけで、一部の行から列のごく一部を取得することがわかっている場合は、場合によっては、可能であれば、評価を延期する 2 番目のアプローチを使用する価値があります。

そうは言っても、実際の値を入力することは本質的にそれほど複雑ではないため、それほど成功する可能性は低いため、より単純な (最初の) アプローチがより適切なオプションである可能性が高くなります。もちろん、特定の行/列をできるだけ早くフィルタリングする必要がないことがわかっている場合 (理想的には、データベースからそれらを取得することさえしない) が最善です。

于 2012-07-24T17:00:39.710 に答える
1

私たちはあなたのためにこれに答えることができるとは思わない. どちらがあなたの状況に適しているかによって異なります。

ただし、個人的には、最初のオプションを使用します。これは、解読がはるかに簡単だからです。十分に文書化されていない限り、将来の開発者はおそらく 2 番目のオプションを見て爆発するでしょう!

于 2012-07-24T16:37:33.353 に答える
1

を使用したソリューションにDictionary<string, Func<object>>は、はるかに多くのオーバーヘッドがあることがわかります。

その理由は、これらのFunc<object>デリゲートは、割り当てが必要なクロージャー オブジェクトに存在するためです。そのコストは、行に 1 回だけインデックスを作成するよりもおそらくはるかに高くなります。

さらに、いずれにせよ後で索引付けを行う必要があるでしょう。を使用したソリューションは、複数の評価を回避するためにFunc<object>、内部にキャッシュを使用することでメリットが得られます。EvaluateExpressionUsingTheseValues(values)しかし、それが最初の解決策です。

于 2012-07-24T16:37:40.953 に答える