1

Delphi列挙子の正規のMoveNextは、次のように記述されます。

function TListEnumerator.MoveNext: Boolean;
begin
  Result := FIndex < FList.Count - 1;
  if Result then
    Inc(FIndex);
end;

これは、RTL、VCLなどで使用されるフォームです。このフォームは、サードパーティのコードでも広く使用されているようです。

私はそれがこのようにもっと簡単に書くことができると思います:

function TListEnumerator.MoveNext: Boolean;
begin
  Inc(FIndex);
  Result := FIndex < FList.Count;
end;

より単純な形式を使用できない理由はありますか?


私の推論は次のとおりです。MoveNextを返すとFalseCurrentプロパティに再度アクセスすることはありません。FIndexそれが二度と使用されることはないので、それがリストの最後から外れていることは問題ではありません。for inループは、実際には次のように実装されます。

while Enumerator.MoveNext do
  Enumerator.Current.DoSomething;

実際FIndex、範囲外になることは私にとってより理にかなっています。これは、誰かが手書きの列挙子コードを使用すると、リターンCurrent後にアクセスされた場合に範囲チェックエラーが発生することを意味します。MoveNextFalse

さらに、FIndex-1の最初の呼び出しの前MoveNextです。それは左側のリストの1つです。そして、への最後の呼び出しの後、MoveNextを返すものFalseは適切ではありませんFIndexCountつまり、右側のリストから1つです。

4

3 に答える 3

4

ループTListEnumeratorでのみ使用されると想定しています。forこれが最も一般的なケースですが、提案されたバージョンは、そうでない場合でも誤動作する可能性があります。MoveNext一度戻った後、もう一度電話をかけるのは問題ありませんFalseMoveNextが返されるまで呼び出しを続けると、無限ループが発生する必要があります。提案されたバージョンでは、ループは無限ではなく、ケースTrueを過ぎると終了します。FIndex = MaxInt

Delphiの実装が基づいているのドキュメントを参照してくださいIEnumerator.MoveNext(IIRC、実際には、現在は機能していないDelphi .NETで最初に利用可能でした)。

列挙子がこの位置にある場合、MoveNextへの後続の呼び出しも、Resetが呼び出されるまでfalseを返します。

于 2012-10-20T18:35:55.530 に答える
2

純粋に意味的に考えると、元のバージョンが正しいと言えます。会話のように考えてください。

Application: Hey, list. Go to the next item.
List: No, sorry. I can't.
Application: Oh, allright.
  <some time later:>
Application: List, please give me the current item
List: No problem, here you go.


Whereas in your suggestion, it would go like this:


Application, Hey, list. Go to the next item.
List: No, that's impossible.
Application: Oh, all right.
  <some time later:>
Application: Hi again, List. Give me the current item.
List: Here you go. 
Application: Thanks, mate.
  <some time later, when using the item:>
Application: What the ????!
于 2012-10-20T18:19:44.967 に答える
1

興味深い質問(+1)。列挙子のすべての可能な使用法(またはその使用法)についての知識がなければ、一見すると、リストの最初と最後でその機能が異なるのは奇妙に見えます。あなたが言うように:最初Currentリストインデックスの範囲外エラーが発生しますが、最後にしないのはなぜですか?一貫性がないようです。

しかし、もう少し考えてみてください。列挙子が作成されると、誰によって、または誰によっても、リストの境界がわからないため、最初の要素はまだ選択できません。これは、境界がわかっていてインデックスがに制限されている場合の最後の動作と比較されます。

BOFデータセットはまったく同じように機能しますが、列挙子の実装は、おそらく-および-のEOFような動作の恩恵を受ける可能性があります。

于 2012-10-21T09:46:58.517 に答える