4

I've created a class which wraps a List:

class Wrapper
{
    private List<int> _list
}

I would like to be able to initialize a new Wrapper object like this:

new Wrapper() {1, 2, 3};

That's supposed to initialize the Wrapper's _list to a list containing {1, 2, 3}.

What do I need to add to the class code in order to enable the functionality?

1

2 Answers 2

5

You need two things:

  • You need to implement IEnumerable (although its behaviour is unimportant for the sake of the collection initializer itself). You don't have to implement the generic version, but you'd normally want to.
  • You need an Add method accepting the element type as a parameter (int in this case)

So the compiler will then transform this:

Wrapper x = new Wrapper() {1, 2, 3};

Into this:

Wrapper tmp = new Wrapper();
tmp.Add(1);
tmp.Add(2);
tmp.Add(3);
Wrapper wrapper = tmp;

The simplest approach would almost certainly be to delegate to your list:

class Wrapper : IEnumerable<int>
{
    private readonly List<int> _list = new List<int>();

    public IEnumerator<int> GetEnumerator()
    {
        return _list.GetEnumerator();
    }

    // Explicit implementation of non-generic interface
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Add(int item)
    {
        _list.Add(item);
    }
}

If you want to make your wrapper slightly more efficient to iterate over, you could change the GetEnumerator methods to include a public one returning List<T>.Enumerator:

// Public method returning a mutable struct for efficiency
public List<T>.Enumerator GetEnumerator()
{
    return _list.GetEnumerator();
}

// Explicit implementation of non-generic interface
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
    return GetEnumerator();
}

// Explicit implementation of non-generic interface
IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}
Sign up to request clarification or add additional context in comments.

1 Comment

"If you want to make your wrapper slightly more efficient to iterate over, you could change the GetEnumerator methods to include a public one returning List<T>.Enumerator:" -- Or, define a custom local struct Enumerator containing a single field of type List<int>.Enumerator, and wrap its methods. It behaves the same, but that IMO makes more sense for the caller, if the caller has a reason to name the enumerator type (as you've done here for List<T>).
2
class ListWrapper :IEnumerable<int>
{
    private List<int> _list = new List<int>();

    public void Add(int i)
    {
        _list.Add(i);
    }

    public IEnumerator<int> GetEnumerator()
    {
        return _list.GetEnumerator();
    }

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.