Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to expose a List<T> as readonly?

Tags:

c#

I've been around this design problem many times, and never found a killer solution.

I want to expose a collection that is editable in the owner class scope, but only readable for other public scopes.

Trial 1:

public class MyClass
{
    private List<object> _myList = new List<object>();

    public IEnumerable<object> MyList { get { return _myList; } }
}

The problem with this is a external code can just cast it back to List and edit, like this:

var x = ((List<object>)MyList);

Trial 2:

public class MyClass
{
    private List<object> _myList = new List<object>();

    public IEnumerable<object> MyList { get { return _myList.ToList(); } }
}

This way we prevent external modification, but create a unnecessary overhead of copying the List many times.

Trial 3:

public class MyClass
{
    private List<object> _myList = new List<object>();
    private ReadOnlyCollection<object> _roList = 
        new ReadOnlyCollection<object>(_myList)

    public IEnumerable<object> MyList { get { return _roList; } }
}

This is the standard solution, wich I use currently, but ReadOnlyCollection is about 30% slower:

Debug Trace:
Use normal foreach on the ReadOnlyCollection
Speed(ms): 2520,3203125
Result: 4999999950000000

use<list>.ForEach
Speed(ms): 1446,1796875
Result: 4999999950000000

Use normal foreach on the List
Speed(ms): 1891,2421875
Result: 4999999950000000

Is there a 'perfect' way of doing this? Thanks.

like image 772
LMB Avatar asked Nov 08 '12 01:11

LMB


People also ask

What read-only list?

UnModifiable Collection Example. Read-only List, Map and Set in Java. A read-only List means a List where you can not perform modification operations like add, remove or set.

Can you add items to a readonly list C#?

In C# there is the readonly keyword that enforced the rule that the variable must be initialised as it's declared or in the constructor. This works as expected for simple types, but for objects and lists it's not quite like that. With a list, you can still add, remove and change items in the list.

What is readonly collection?

ReadOnlyCollection makes an array or List read-only. With this type from System. Collections. ObjectModel, we provide a collection of elements that cannot be changed.


2 Answers

Have you tried returning the enumerator?

public class MyClass
{
    private List<object> _myList = new List<object>();

    public IEnumerable<object> MyList { get { yield return _myList.GetEnumerator(); } }
}

This doesn't create a copy, is readonly, and cannot be cast back to list.

Edit: this only works with yield return. It is lazy evaluated this way, I do not know whether that is an issue for you or not.

like image 71
Paul Phillips Avatar answered Nov 03 '22 00:11

Paul Phillips


You can use List<T>.AsReadOnly method to expose a thin read-only wrapper of your list. There will be no additional copying, and the caller will "see" changes to the original array done inside your method instantaneously:

public ReadOnlyCollection<object> MyList { get { return _myList.AsReadOnly(); } }
like image 26
Sergey Kalinichenko Avatar answered Nov 02 '22 23:11

Sergey Kalinichenko