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?

snakile
  • 52,936
  • 62
  • 169
  • 241

2 Answers2

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();
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • "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.Enumerator:" -- Or, define a custom local `struct Enumerator` containing a single field of type `List.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`). –  Dec 11 '12 at 07:48
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();
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224