By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,934 Members | 1,692 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,934 IT Pros & Developers. It's quick & easy.

Creating a Custom Enumerator in a Base Class

P: n/a
I have a base class MyBaseClass, and several classes that inherit from it:
MyClass1, MyClass2, etc.

The base class implements IEnumerable(Of IMyBaseClassRow). The base class
has a DataTable object that contains different data depending on which of
MyClass1, MyClass2 are instantiated.

I want to be able to iterate through the rows of the data table using For
Each on my derived classes retrieving a custom row with properties specific
to that child class. I found this article

http://blog.falafel.com/2007/01/30/C...Iterators.aspx

which alludes to the technique, but doesn't go all the way to showing how to
derive custom row classes with the properties. I am also doing this in VB,
so I don't have Yield Return. Therefore, I am having to code this all by
hand.

I want all the enumeration stuff in the base class, so that I don't have to
reproduce it in every derived class, but I have one stumbling block. This is
my implementation of Current() in my base class:

Private ReadOnly Property Current() As IMyBaseClassRow Implements
System.Collections.Generic.IEnumerator(Of IMyBaseClassRow).Current
Get
If m_CurrentRow = -1 Or m_CurrentRow >
m_MyBaseClass.DataTable.Rows.Count - 1 Then
Throw New InvalidOperationException
End If

Return New
MyBaseClassRow(m_MyBaseClass.DataTable.Rows(m_Curr entRow))
End Get
End Property

The problem is that this can only return a new MyBaseClassRow, and not a
MyClass1Row. Therefore, when I do

For Each row As MyClass1Row in MyClass1Instance
...
Next

the compiler is happy, but it fails at runtime with an InvalidCastException
on the For Each line.

I think I need to override something in my MyClass1 or MyClass1Row class,
but I'm not sure what exactly, or how.

If this problem makes sense to anyone, please feel free to chip in. Any and
all help welcome.

TIA

Charles
Sep 19 '08 #1
Share this Question
Share on Google+
1 Reply


P: n/a
I think I've cracked it.

In my base class MyBaseClass, I have created a must override function that
returns an object of the type I want, i.e.

Protected MustOverride Function GetIMyBaseClassRow(dr As DataRow) As
IMyBaseClassRow

In my concrete class, I then override this function:

Protected Overrides Function GetIMyBaseClassRow(ByVal dr As
System.Data.DataRow) As IMyBaseClassRow
Return New MyClass1Row(dr)
End Function

Finally, Current() in MyBaseClass becomes this:

Private ReadOnly Property Current() As IMyBaseClassRow Implements
System.Collections.Generic.IEnumerator(Of IMyBaseClassRow).Current
Get
If m_CurrentRow = -1 Or m_CurrentRow >
m_MyBaseClass.DataTable.Rows.Count - 1 Then
Throw New InvalidOperationException
End If

Return
GetIMyBaseClassRow(m_MyBaseClass.DataTable.Rows(m_ CurrentRow))
End Get
End Property

It allows the base class to call the derived class to get an object of the
actual type required.

I hope this helps someone.

If anyone has another solution, I am still very interested to hear.

Charles
"Charles Law" <bl***@nowhere.comwrote in message
news:OW**************@TK2MSFTNGP04.phx.gbl...
>I have a base class MyBaseClass, and several classes that inherit from it:
MyClass1, MyClass2, etc.

The base class implements IEnumerable(Of IMyBaseClassRow). The base class
has a DataTable object that contains different data depending on which of
MyClass1, MyClass2 are instantiated.

I want to be able to iterate through the rows of the data table using For
Each on my derived classes retrieving a custom row with properties
specific to that child class. I found this article

http://blog.falafel.com/2007/01/30/C...Iterators.aspx

which alludes to the technique, but doesn't go all the way to showing how
to derive custom row classes with the properties. I am also doing this in
VB, so I don't have Yield Return. Therefore, I am having to code this all
by hand.

I want all the enumeration stuff in the base class, so that I don't have
to reproduce it in every derived class, but I have one stumbling block.
This is my implementation of Current() in my base class:

Private ReadOnly Property Current() As IMyBaseClassRow Implements
System.Collections.Generic.IEnumerator(Of IMyBaseClassRow).Current
Get
If m_CurrentRow = -1 Or m_CurrentRow >
m_MyBaseClass.DataTable.Rows.Count - 1 Then
Throw New InvalidOperationException
End If

Return New
MyBaseClassRow(m_MyBaseClass.DataTable.Rows(m_Curr entRow))
End Get
End Property

The problem is that this can only return a new MyBaseClassRow, and not a
MyClass1Row. Therefore, when I do

For Each row As MyClass1Row in MyClass1Instance
...
Next

the compiler is happy, but it fails at runtime with an
InvalidCastException on the For Each line.

I think I need to override something in my MyClass1 or MyClass1Row class,
but I'm not sure what exactly, or how.

If this problem makes sense to anyone, please feel free to chip in. Any
and all help welcome.

TIA

Charles


Sep 19 '08 #2

This discussion thread is closed

Replies have been disabled for this discussion.