2

Delphi には、配列の最下位および最上位のインデックス次元を返す Low() および High() 関数があります。これは、 for ループステートメント の終了条件に<を意味するときに<=を使用するなど、陰湿な​​ +1/-1 配列境界エラーの犠牲になる可能性のある配列を反復するためのエラーが発生しやすいfor ループを排除するのに役立ちます。

以下は、Low/High 関数の例です (Delphi で)。

for i := Low(ary) to High(ary) do

今のところ、C# で単純なfor ループステートメントを使用しています。

for (int i = 0; i < ary.Length; i++)

Array メソッドGetDimension(N)があることは知っていますが、間違った次元インデックスを誤って使用してエラーを引き起こす可能性があるため、それには独自の責任があります。列挙子で何かできると思いますが、for loopを使用する場合と比較して、大きな配列をスキャンするとパフォーマンスが大幅に低下するのではないかと心配しています。C# で High/Low に相当するものはありますか?

4

4 に答える 4

11

low(ary)組み込み関数と関数に相当する C#high(ary)は、それぞれ0ary.Length-1です。これは、C# 配列がゼロ ベースであるためです。Length配列のプロパティが、Delphi の とは異なるパフォーマンス特性を持つべき理由がわかりませんhigh()

パフォーマンスの点で、Pascal ループと C 派生言語で使用されるループとの大きな違いforは、終了テストの評価に関するものです。古典的な Pascalforループを考えてみましょう:

for i := 0 to GetCount()-1 do
  ....

PascalforループでGetCount()は、ループの開始時に 1 回だけ評価されます。

次に、C 派生言語で同等のものを考えてみましょう。

for (int i=0; i<GetCount(); i++)
  ....

このループでGetCount()は、ループを一巡するたびに評価されます。したがって、C# のような言語では、その関数を何度も呼び出すのを避けるために、ローカル変数が必要になります。

int N = GetCount();
for (int i=0; i<N; i++)
  ....

配列の場合、ary.Lengthオプティマイザーがループ中に変化しなかったことを確認できれば、コードはコンパイラーによって最適化されます。個人的には、C# オプティマイザーがそれを行うかどうかはわかりませんが、詳細についてはコメントを参照してください。

配列の長さを含むローカル変数を使用するようにループを書き直す前に、違いがあるかどうかを確認してください。ほぼ間違いないでしょう。上で概説した Pascal と C に似た for ループの違いは、おそらくパフォーマンスよりもセマンティックの面で重要です。


私が特にうらやましい言語は D です。ここではforeach、配列内の各項目を参照として提示するループを使用できるため、配列の内容を変更できます。

void IncArray(int[] array, int increment) {
    foreach (ref e; array) {
        e += increment;
    }
}    
于 2013-03-24T19:01:36.180 に答える
4

C# では、下限は常に 0 であるため、Low(ary)is justに相当し0ます。

1 次元配列の場合、 is と同等High(ary)ですary.Length - 1。(多次元配列の場合、とにかく複数のループが必要になります。)

于 2013-03-24T19:02:33.700 に答える
1

foreach代わりにステートメントを使用できますか?お気に入り

foreach(int i in ary)
{
. . .
}
于 2013-03-24T19:00:08.667 に答える
1

[境界(整数次元)]

これらの境界関数は、任意の配列のユーザー指定の次元の開始点と終了点を提供します。2 番目の次元は、ゼロではなく 1 で示されます。

for (int i = ary.GetLowerBound(0); i <= ary.GetUpperBound(0); i++ )
{}
于 2015-07-14T14:12:06.337 に答える