ProgrammingVB.NET開発者

Visual Basicにおけるカスタムコレクションを使ったFor...Each...Nextループの動作について説明してください。For Eachで反復処理するための独自のコレクションを作成するには、何を実装する必要がありますか?

Hintsage AIアシスタントで面接を突破

回答。

質問の背景:

Visual BasicのFor Each...Next文は、コレクションや配列の要素を反復処理することを可能にします。VB6からは標準コレクションの反復処理がサポートされ、VB.NETでは特定のインターフェースを実装するすべての型に対応しています。しかし、独自のコレクションを作成して独自の反復処理を行う必要がある場合、必要なインフラストラクチャを正しく実装することが重要です。

問題

要素の保存だけを実装するだけでは不十分です。For Each文は、IEnumerableインターフェースのサポートを必要とします。しばしば、カスタムコレクションの実装はAdd/Getメソッドに制限され、オブジェクトは反復処理のための「ブラックボックス」と化のります。これは、反復処理の言語構造との統合を妨げ、エラーを引き起こします。

解決策

For Eachがあなたのコレクションで正しく動作するためには、IEnumerableインターフェースを実装し、型指定要素との連携をサポートするためにIEnumerable(Of T)を実装する必要があります。また、IEnumeratorインターフェースを実装する独自の列挙子(Enumerator)を作成する必要があります(またはジェネリックバージョンの場合はIEnumerator(Of T)を)。

例:

Public Class IntCollection Implements IEnumerable(Of Integer) Private ReadOnly items As New List(Of Integer)() Public Sub Add(value As Integer) items.Add(value) End Sub Public Function GetEnumerator() As IEnumerator(Of Integer) _ Implements IEnumerable(Of Integer).GetEnumerator Return items.GetEnumerator() End Function Private Function IEnumerable_GetEnumerator() As IEnumerator _ Implements IEnumerable.GetEnumerator Return GetEnumerator() End Function End Class ' 使用方法: Dim col As New IntCollection() col.Add(10) col.Add(20) col.Add(30) For Each n As Integer In col Console.WriteLine(n) Next

主な特徴:

  • GetEnumeratorメソッドを実装し、IEnumeratorまたはIEnumerator(Of T)を返す必要があります。
  • 異なる環境バージョンとの互換性のため、ジェネリックおよび非ジェネリックのIEnumerableをサポートします。
  • 完全なコレクションは、LINQ、For Eachに参加し、.NETの標準インフラストラクチャと共に動作します。

質問の背後にある罠。

インターフェースIEnumerableなしで、単にGetEnumeratorメソッドを書くだけでFor Eachを実装できますか?

いいえ、Visual BasicはCollectionsがFor Eachと互換性を持つとコンパイラが認識するために、IEnumerable/IEnumerable(Of T)インターフェースの公式サポートを必要とします。

列挙子は別のクラスである必要がありますか?

いいえ、要素データベースが標準の列挙子をサポートしている場合(例えば、List(Of T)を集約している場合)、そのGetEnumeratorを返すことができます。複雑なシナリオの場合は、独自のIEnumerator実装クラスが必要な場合があります。

For Eachループ内でコレクションを変更することは可能ですか?

いいえ、反復中にコレクションを変更するとInvalidOperationExceptionが発生します。適切な処理には特別な戦略(例:反復処理前にリストをコピーする、またはインデクシングを使用する)を必要とします。

一般的なエラーとアンチパターン

  • IEnumerableなしでのAdd/Removeの実装 — For Eachを使用できません。
  • 存在しないまたは不正なEnumeratorを返すこと — 反復処理中にクラッシュを引き起こします。
  • For Eachループ内でコレクションを変更します。

事例

ネガティブケース

会社では、IEnumerableインターフェースを実装せずに、配列を介して追加および削除するMyCollectionクラスを独自に開発しました。しかし、For Eachは機能せず、通常のループと要素を含む公開フィールドを使用する必要がありました。

利点:

  • コレクションの迅速な作成 — コードは最小限。

欠点:

  • For EachやLINQを使用できず、標準コレクションのように扱えませんでした。
  • 異なる場所での反復処理の重複コードが発生しました。

ポジティブケース

クラスを改造し、IEnumerable(Of T)を実装しました。その後、コレクションはFor Eachに標準的に簡単に使用でき、LINQとの互換性も確保されました。

利点:

  • クリーンで標準的な構文。
  • コレクションの反復処理は、VB.NETのすべてのインフラストラクチャ機能と互換性があります。

欠点:

  • インターフェースをサポートするために、より多くのコードを追加する必要があります。