问题
Arrays are a fast way to iterate through an unordered set of items, and it's often nice for them to be read-only. While exposing arrays with the `readonly' keyword is useless because the contents of the array can still be altered, a ReadOnlyCollection<T> wrapper solves this. The problem is it's 4 times slower than a plain array in tests I've done. (I know, returning a copy of the array would only take a performance hit once, but ideally I wouldn't want to waste CPU time on that either.)
I have noticed I can get the benefit of a read-only sanity-check while preserving the performance of a plain array with a class like this:
class ReadOnlyArray<T>
{
    private readonly T[] array;
    public ReadOnlyArray(T[] a_array)
    {
        array = a_array;
    }
    // read-only because no `set'
    public T this[int i]
    { get { return array[i]; } }
    public int Length
    { get { return array.Length; } }
}
The problem is I lose the convenience of the foreach() syntax. I.e. I have to iterate through it with a for(;;) loop in order to keep the performance. -- I used to write C code, where every loop was a for(;;). Maybe I've become spoiled. -- If I implement IEnumerable<T> then I get the same performance as ReadOnlyCollection<T>, and this class is useless.
Any idea how to achieve the perfect combination of all 3 goals: a read-only sanity check, no performance loss, and the convenient foreach() syntax?
回答1:
I think the below does what you want. However, I think this is actually inadvisable. You're imposing an unnecessary and potentially confusing abstraction. Yes, the JIT will probably optimize it eventually, and your coworkers should catch on. But you're still doing something the language isn't meant to do.
EDIT: I've tweaked and better explained the below code, and mentioned a couple of options.
using System.Collections;
using System.Collections.Generic;
/*
  You can leave off the interface, or change to IEnumerable.  See below.
*/
class ReadOnlyArray<T> : IEnumerable<T>
{
    private readonly T[] array;
    public ReadOnlyArray(T[] a_array)
    {
        array = a_array;
    }
    // read-only because no `set'
    public T this[int i]
    { get { return array[i]; } }
    public int Length
    { get { return array.Length; } }
    /* 
       You can comment this method out if you don't implement IEnumerable<T>.
       Casting array.GetEnumerator to IEnumerator<T> will not work.
    */
    public IEnumerator<T> GetEnumerator()
    {
        foreach(T el in array)
        {
            yield return el;
        }
    }
    /* 
       If you don't implement any interface, change this to:
       public IEnumerator GetEnumerator()
       Or you can implement only IEnumerable (rather than IEnerable<T>)
       and keep "IEnumerator IEnumerable.GetEnumerator()"
    */
    IEnumerator IEnumerable.GetEnumerator()
    {
        return array.GetEnumerator();
    }
}
    回答2:
Arrays are a fast way to iterate through an unordered set of items,
If that's all you need to do, just return the array as an IEnumerable.  Don't implement IEnumerable yourself: the array already does that.
That should meet all three of your goals.
public class SomeClass
{ 
    private T[] myArray; // T could be any type
    public IEnumerable<T> MyReadOnlyArray { get { return myArray; } }
}
    来源:https://stackoverflow.com/questions/953289/read-only-array-in-net