10

Say, we have a generic class with a private List. We can make it return a readonly wrapper of this list at least with two ways:

public class Test<T>
{
    public List<T> list = new List<T>();

    public IEnumerable<T> Values1
    {
        get
        {
            foreach (T i in list)
                yield return i;
        }
    }

    public IEnumerable<T> Values2
    {
        get
        {
            return list.AsReadOnly();
        }
    }
}

Both Values1 and Values2 reflect any chages in the underlying collection and prevent it from modifying through themselves.

Which way if preferable? What should one be aware of? Or is there any other better way?

devuxer
  • 41,681
  • 47
  • 180
  • 292
horgh
  • 17,918
  • 22
  • 68
  • 123

1 Answers1

12

If only an IEnumerable<T> is required for the output, I prefer:

public IEnumerable<T> Values
{
    return this.list.AsReadOnly();
}

Since ReadOnlyCollection<T> implements IEnumerable<T>, this provides a safe wrapper around your objects, while still being flexible and efficient, and preventing a cast from being able to set values.

You can always change the internal implementation later if you decide you need to do something different in the results.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    I'm going to second Reed here - the construction of the ReadOnly collection literally just wraps the existing list, so it's a very inexpensive call; it implements IEnumerable, so it's completely compatible there; it implements ICollection, so you get fast Count access. All around goodness! – JerKimball Oct 02 '12 at 01:52
  • "preventing a cast from being able to set values". Casting the result of the getter in the first case should not make it possible to add/remove values to the original `list`? Because you're then supposed to work with a copy of the original one anyway, or I misunderstood what you mean? – Guillaume Oct 02 '12 at 02:20
  • Surely, if use a list generated by `test.Values1.ToList()`, it's gonna be a copy. – horgh Oct 02 '12 at 02:26
  • The result is also similar for `yield return` and `AsReadOnly()` in this case – horgh Oct 02 '12 at 02:29
  • Yes. Result is similar in all cases. `yield return` will generate a new (compiler generated) type. `AsReadOnly` uses a framework type. It's all an implementation detail, but this is my preference. – Reed Copsey Oct 02 '12 at 16:02