You would expose it as an IEnumerable<T>
, but not just returning it directly:
public IEnumerable<object> Objects { get { return obs.Select(o => o); } }
Since you indicated you only wanted traversal of the list, this is all you need.
One might be tempted to return the List<object>
directly as an IEnumerable<T>
, but that would be incorrect, because one could easily inspect the IEnumerable<T>
at runtime, determine it is a List<T>
and cast it to such and mutate the contents.
However, by using return obs.Select(o => o);
you end up returning an iterator over the List<object>
, not a direct reference to the List<object>
itself.
Some might think that this qualifies as a "degenerate expression" according to section 7.15.2.5 of the C# Language Specification. However, Eric Lippert goes into detail as to why this projection isn't optimized away.
Also, people are suggesting that one use the AsEnumerable extension method. This is incorrect, as the reference identity of the original list is maintained. From the Remarks section of the documentation:
The AsEnumerable<(Of
<(TSource>)>)(IEnumerable<(Of
<(TSource>)>)) method has no effect
other than to change the compile-time
type of source from a type that
implements IEnumerable<(Of <(T>)>) to
IEnumerable<(Of <(T>)>) itself.
In other words, all it does is cast the source parameter to IEnumerable<T>
, which doesn't help protect referencial integrity, the original reference is returned and can be cast back to List<T>
and be used to mutate the list.