3

数组是迭代无序项集的一种快速方法,而且它们通常是只读的。虽然使用 `readonly' 关键字公开数组是无用的,因为数组的内容仍然可以更改,但 ReadOnlyCollection<T> 包装器解决了这个问题。问题是它比我所做的测试中的普通数组慢 4 倍。(我知道,返回数组的副本只会对性能造成一次影响,但理想情况下我也不想在这上面浪费 CPU 时间。)

我注意到我可以获得只读完整性检查的好处,同时保留具有如下类的普通数组的性能:

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; } }
}

问题是我失去了 foreach() 语法的便利性。即,为了保持性能,我必须使用 for(;;) 循环遍历它。-- 我曾经写过 C 代码,其中每个循环都是一个 for(;;)。也许我已经被宠坏了。-- 如果我实现 IEnumerable<T>,那么我得到的性能与 ReadOnlyCollection<T> 相同,而这个类是没用的。

知道如何实现所有 3 个目标的完美结合:只读的完整性检查、没有性能损失和方便的 foreach() 语法?

4

2 回答 2

4

我认为以下内容可以满足您的要求。但是,我认为这实际上是不可取的。您正在强加一个不必要且可能令人困惑的抽象。是的,JIT 最终可能会对其进行优化,而您的同事应该会赶上。但是你仍然在做一些语言不应该做的事情。

编辑:我已经调整并更好地解释了下面的代码,并提到了几个选项。

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();
    }
}
于 2009-06-04T21:51:47.903 回答
0

数组是一种快速遍历无序项集的方法,

如果这就是您需要做的所有事情,只需将数组作为IEnumerable. 不要自己实现 IEnumerable:数组已经这样做了。

这应该满足您的所有三个目标。

public class SomeClass
{ 
    private T[] myArray; // T could be any type

    public IEnumerable<T> MyReadOnlyArray { get { return myArray; } }
}
于 2009-06-04T22:16:23.487 回答