Programmingライブラリ開発者 .NET / 中級 VB.NET デベロッパー

Visual Basicにおけるイテレータ(Enumerable / Iterator)の実装と利用方法、ならびに独自の列挙可能コレクションを作成する方法について説明してください。

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

回答。

質問の背景
イテレータは、コレクションを反復処理する必要が出てきたことで、プログラミング言語の重要な部分となりました。Visual Basicでは、.NETバージョンからIEnumerable/IEnumeratorのサポートが追加され、独自の列挙可能コレクションを実装したり、For Eachループを使用してコレクションの内容に便利で簡潔にアクセスすることが可能となりました。

問題
多くの開発者は、組み込みコレクションのみを使用するか、IEnumerableインターフェイスを正しく実装しないため、For Eachによるオブジェクトの反復が不可能になる場合があります。また、CurrentやMoveNextを介したイテレータの状態管理が複雑になります。

解決策
反復処理をサポートするために、型はIEnumerable(またはジェネリックIEnumerable(Of T))インターフェイスを実装します。IEnumeratorを実装したオブジェクトを返すGetEnumerator関数を実装してください。VB.NETではVB 2015以降、Yieldキーワードを用いたイテレーターメソッドも利用できます。これにより、反復処理の実装が大幅に簡素化されます。

コードの例:

Imports System.Collections Public Class SimpleCollection Implements IEnumerable Private arr() As Integer = {1, 2, 3} Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator For Each i In arr Yield i ' VB 2015以降 Next End Function End Class ' 使用方法: For Each n As Integer In New SimpleCollection() Console.WriteLine(n) Next

主な特徴:

  • For Eachをサポートするためには、型はIEnumerable / IEnumerable(Of T)を実装する必要があります。
  • 実装は通常、既存のコレクションに委譲されたり、独自の構造が作成されたりします。
  • Yieldを使うことでイテレータを簡単に作成できます;Yieldを使わない場合は手動でIEnumeratorを実装する必要があります。

ひねりのある質問。

For Eachをサポートするために、IEnumerableとIEnumeratorの両方のインターフェイスを実装する必要がありますか?

いいえ、IEnumerableを実装し、互換性のあるイテレータを返すだけで十分です。反復処理を実装したい場合は、内包されているコレクションの既存のIEnumeratorを使用できます。ただし、完全なカスタマイズを行うには両方の部分を実装する必要があります。

コードの例:

Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return arr.GetEnumerator() ' 組み込みの配列イテレータを使用 End Function

Visual BasicでIEnumerableを明示的に(Explicit Interface Implementation)実装できますか?

はい、特にコレクションに自分自身のGetEnumeratorがあり、インターフェイスの実装を隠したい場合には、明示的にインターフェイスを実装することができます。このようなGetEnumeratorを直接呼び出すことはできませんが、For Eachは機能します。

コードの例:

Public Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator ' ...メソッドの本体 End Function

GetEnumeratorがNothingを返すとどうなりますか?

コレクションの最初の反復試行時に例外がスローされます。For Eachは正しいイテレータを期待するためです。

典型的なエラーとアンチパターン

  • MoveNext/Currentメソッドの不正な実装により、要素がスキップされたりエラーが発生します。
  • 呼び出し間でイテレータの状態が乱れる(例えば、再反復時にインデックスがリセットされない)。
  • StopIterationの欠如または不正な例外。

実例

ネガティブケース

コレクションクラスがIEnumerableを実装しておらず、要素を反復処理するための個別のNextメソッドが作成されました。結果として、一般的なメソッドやFor Eachでは使用できなくなり、追加のメソッドを書く必要があります。

利点:

  • 要件に対する迅速な実装。

欠点:

  • For EachおよびLINQを使用できない。
  • .NET APIとの互換性を失う。

ポジティブケース

開発者がIEnumerableとGetEnumeratorを実装し、コレクションがFor Eachで機能し、LINQと統合されました。

利点:

  • .NETインフラストラクチャとの完全な互換性。
  • 汎用性と使いやすさ。

欠点:

  • Yieldが導入される前の手動実装では、少しコードが多くなります。