Matt
Matt

Reputation: 22123

How can I create a typed IEnumerable in C#?

I can do this:

public class EnumerableTest : System.Collections.IEnumerable
{
    System.Collections.IEnumerable data;

    public EnumerableTest(System.Collections.IEnumerable d)
    {
        data = d;
    }

    public System.Collections.IEnumerator GetEnumerator()
    {
        foreach (object s in data)
        {
            yield return s;
        }
    }
}

But I can't do this?:

public class EnumerableTestString : System.Collections.Generic.IEnumerable<string>
{
    System.Collections.Generic.IEnumerable<string> data;

    public EnumerableTestString(System.Collections.Generic.IEnumerable<string> d)
    {
        data = d;
    }

    public System.Collections.Generic.IEnumerator<string> GetEnumerator()
    {
        foreach (string s in data)
        {
            yield return s;
        }
    }
}

The error I get basically says I am missing the method

    public System.Collections.IEnumerator GetEnumerator();

When I change the return type of GetEnumerator() to that, then it tells me I am missing

    public System.Collections.Generic.IEnumerator<string> GetEnumerator();

If I try to include both, it tells me I have a duplicate method name.

How can I solve this?

Upvotes: 4

Views: 445

Answers (3)

Blachshma
Blachshma

Reputation: 17395

Create both - e.g. an Explicit implementation that will call the Implicit implementation.

Example:

public class EnumerableTestString : System.Collections.Generic.IEnumerable<string>
{
    System.Collections.Generic.IEnumerable<string> data;

    public EnumerableTestString(System.Collections.Generic.IEnumerable<string> d)
    {
        data = d;
    }

    public System.Collections.Generic.IEnumerator<string> GetEnumerator()
    {
        foreach (string s in data)
        {
            yield return s;
        }
    }

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

Upvotes: 7

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112392

Implement System.Collections.Generic.IEnumerable<T> instead.

When you do so using VS's smart tag, VS automatically creates two methods. One for the generic implementation and one for the non-generic one (the one you have already) because IEnumerable<T> requires you to implement IEnumerable as well.

public class StringData : IEnumerable<string>
{
    ...

    #region IEnumerable<string> Members

    public IEnumerator<string> GetEnumerator()
    {
        foreach (string s in data) {
            yield return s;
        }
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();  // Calls generic GetEnumerator
    }

    #endregion
}

Note that the non generic method is implemented explicitly and can therefore only be accessed through the interface (IEnumerable x = ...; x.GetEnumerator()). Its purpose is to increase the compatibility and is a remnant of pre-generic c# versions (1.0, 1.1).

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500805

How can I solve this?

You need to use explicit interface implementation to implement at least one of the GetEnumerator methods, usually the non-generic one.

The code is simply with using directives :)

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

public class EnumerableTestString : IEnumerable<string>
{
    private IEnumerable<string> data;

    public EnumerableTestString(IEnumerable<string> d)
    {
        data = d;
    }

    public IEnumerator<string> GetEnumerator()
    {
        foreach (string s in data)
        {
            yield return s;
        }
    }

    // Explicit interface implementation for non-generic IEnumerable
    public IEnumerator IEnumerable.GetEnumerator()
    {
        // Delegate to the generic version
        return GetEnumerator();
    }
}

Upvotes: 9

Related Questions