Implementing a Enumerator interface

S

Senthil

Hi ,
I am learning C# and now am stuck with a simple prorgam.Tried googling
but didn't get an answer :(. The following program gives me three
compilation errors.Can anyone enlighten me? Thanks.

using System;
using System.Collections.Generic;
using System.Text;

namespace Collections
{
public class Tokens : IEnumerable<String>
{
private String[] elements;

Tokens(String source, char[] delimiters)
{
elements = source.Split(delimiters);
}

~Tokens()
{
}

public IEnumerator<String> GetEnumerator()
{
return new TokenEnumerator(this);
}

private class TokenEnumerator:IEnumerator<String>
{
private Int32 pos = -1;
private Tokens t;

public TokenEnumerator(Tokens tok)
{
t = tok;
}

public Boolean MoveNext()
{
if (pos < t.elements.Length - 1)
{
pos++;
return true;
}
else
{
return false;
}
}

public void Reset()
{
pos = -1;
}

public String Current
{
get { return t.elements[pos]; }
}
}

public static void Main()
{
Tokens f = new Tokens("This is my first C# program", new
char[] { ' ', '#' });
foreach (String s in f)
{
Console.WriteLine(s);
}
}
}
}

Error 1 'Collections.Tokens.TokenEnumerator' does not implement
interface member 'System.IDisposable.Dispose()'
Error 2 'Collections.Tokens.TokenEnumerator' does not implement
interface member 'System.Collections.IEnumerator.Current'.
'Collections.Tokens.TokenEnumerator.Current' is either static, not
public, or has the wrong return type

Error 3 'Collections.Tokens' does not implement interface member
'System.Collections.IEnumerable.GetEnumerator()'.
'Collections.Tokens.GetEnumerator()' is either static, not public, or
has the wrong return type.
 
C

Carl Daniel [VC++ MVP]

Senthil said:
Hi ,
I am learning C# and now am stuck with a simple prorgam.Tried googling
but didn't get an answer :(. The following program gives me three
compilation errors.Can anyone enlighten me? Thanks.

First, since you're using C# 2.0, it's much (much, much!) easier to use the
new interator syntax that's built into the language (look up 'yield return'
in the C# language reference). See additional comments about the errors
you're getting inline, below.
using System;

Add:

using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Collections
{
public class Tokens : IEnumerable<String>
{
private String[] elements;

Tokens(String source, char[] delimiters)
{
elements = source.Split(delimiters);
}

~Tokens()
{
}

public IEnumerator<String> GetEnumerator()
{
return new TokenEnumerator(this);
}

You also need

IEnumerator IEnumerable.GetEnumerator()
{
return new TokenEnumerator(this);
}

to supply an implementation for IEnumerable.GetEnumerator, since
IEnumerable said:
private class TokenEnumerator:IEnumerator<String>
{
private Int32 pos = -1;
private Tokens t;

public TokenEnumerator(Tokens tok)
{
t = tok;
}

public Boolean MoveNext()
{
if (pos < t.elements.Length - 1)
{
pos++;
return true;
}
else
{
return false;
}
}

public void Reset()
{
pos = -1;
}

public String Current
{
get { return t.elements[pos]; }
}

This supplies IEnumerator<string>.Current, but you also need

object IEnumerator.Current
{
get {re turn t.elements[pos]; }
}

to supply an implementation of IEnumerator.Current since IEnumerator<sT>
derives from IEnumerator.


You also need

void IDisposable.Dispose()
{
}

since IEnumerator said:
}

public static void Main()
{
Tokens f = new Tokens("This is my first C# program", new
char[] { ' ', '#' });
foreach (String s in f)
{
Console.WriteLine(s);
}
}
}
}
 
B

Barry Kelly

Senthil said:
I am learning C#

I see you are using C# 2.0.
and now am stuck with a simple prorgam.Tried googling
but didn't get an answer :(. The following program gives me three
compilation errors.Can anyone enlighten me? Thanks.

I'll go through the errors first, before I deal with the code.
Error 1 'Collections.Tokens.TokenEnumerator' does not implement
interface member 'System.IDisposable.Dispose()'

This refers to the fact that IEnumerator<T> descends from IDisposable,
Error 2 'Collections.Tokens.TokenEnumerator' does not implement
interface member 'System.Collections.IEnumerator.Current'.
'Collections.Tokens.TokenEnumerator.Current' is either static, not
public, or has the wrong return type

This refers to the fact that IEnumerator<T> also descends from
IEnumerator, and the IEnumerator.Current property is of type 'object',
not 'string'. You'd need an explicit implementation, like this:

object IEnumerator.Current
{
get { return Current; } // uses the Current of type 'string'
}
Error 3 'Collections.Tokens' does not implement interface member
'System.Collections.IEnumerable.GetEnumerator()'.
'Collections.Tokens.GetEnumerator()' is either static, not public, or
has the wrong return type.

This is similar to the error for Current. Again, you need an explicit
implementation:

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

Note that calling methods like this, inside the type, never resolves to
an explicit interface method implementation. So, this won't recurse
indefinitely.
using System;
using System.Collections.Generic;
using System.Text; [...]
~Tokens()
{
}
This is a finalizer. It is *highly* unlikely that your type needs a
finalizer, and its presence will make your class a lot less efficient
than it can be.

Finally, I'd like to point you to iterators, a feature of C# 2.0 which
make implementing enumerators a lot easier (ignoring the fact that you
could just return 'elements.GetEnumerator()'). Your program could be
written with iterators in the following manner:

---8<---
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Collections
{
public class Tokens : IEnumerable<String>
{
private String[] elements;

Tokens(String source, char[] delimiters)
{
elements = source.Split(delimiters);
}

~Tokens()
{
}

public IEnumerator<String> GetEnumerator()
{
for (int i = 0; i < elements.Length; ++i)
yield return elements;
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public static void Main()
{
Tokens f = new Tokens("This is my first C# program", new
char[] { ' ', '#' });
foreach (String s in f)
{
Console.WriteLine(s);
}
}
}
}
--->8---

-- Barry
 
S

Senthil

Barry said:
Senthil said:
I am learning C#

I see you are using C# 2.0.
and now am stuck with a simple prorgam.Tried googling
but didn't get an answer :(. The following program gives me three
compilation errors.Can anyone enlighten me? Thanks.

I'll go through the errors first, before I deal with the code.
Error 1 'Collections.Tokens.TokenEnumerator' does not implement
interface member 'System.IDisposable.Dispose()'

This refers to the fact that IEnumerator<T> descends from IDisposable,
Error 2 'Collections.Tokens.TokenEnumerator' does not implement
interface member 'System.Collections.IEnumerator.Current'.
'Collections.Tokens.TokenEnumerator.Current' is either static, not
public, or has the wrong return type

This refers to the fact that IEnumerator<T> also descends from
IEnumerator, and the IEnumerator.Current property is of type 'object',
not 'string'. You'd need an explicit implementation, like this:

object IEnumerator.Current
{
get { return Current; } // uses the Current of type 'string'
}
Error 3 'Collections.Tokens' does not implement interface member
'System.Collections.IEnumerable.GetEnumerator()'.
'Collections.Tokens.GetEnumerator()' is either static, not public, or
has the wrong return type.

This is similar to the error for Current. Again, you need an explicit
implementation:

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

Note that calling methods like this, inside the type, never resolves to
an explicit interface method implementation. So, this won't recurse
indefinitely.
using System;
using System.Collections.Generic;
using System.Text; [...]
~Tokens()
{
}
This is a finalizer. It is *highly* unlikely that your type needs a
finalizer, and its presence will make your class a lot less efficient
than it can be.

Finally, I'd like to point you to iterators, a feature of C# 2.0 which
make implementing enumerators a lot easier (ignoring the fact that you
could just return 'elements.GetEnumerator()'). Your program could be
written with iterators in the following manner:

---8<---
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Collections
{
public class Tokens : IEnumerable<String>
{
private String[] elements;

Tokens(String source, char[] delimiters)
{
elements = source.Split(delimiters);
}

~Tokens()
{
}

public IEnumerator<String> GetEnumerator()
{
for (int i = 0; i < elements.Length; ++i)
yield return elements;
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public static void Main()
{
Tokens f = new Tokens("This is my first C# program", new
char[] { ' ', '#' });
foreach (String s in f)
{
Console.WriteLine(s);
}
}
}
}
--->8---

-- Barry


Thanks for your replies folks!!!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top