只读在.NET中的数组数组、NET

2023-09-03 02:59:17 作者:我是你的未来つ

数组是一个快速的方式来遍历一个无序的项目,而且它往往不错的他们是只读的。虽然露出阵列的'只读'关键字是没用的,因为数组的内容仍然可以改变,一个ReadOnlyCollection还< T>包装解决这个问题。现在的问题是,它比普通的数组中测试中,我所做的要慢4倍。 (我知道,返回数组的一个副本将只需要一个性能命中一次,但最好我不想浪费CPU时间,要么。)

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.)

我注意到我可以得到一个只读的完整性检查的好处,而preserving普通阵列的性能一类是这样的:

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

现在的问题是我失去的foreach()语法的便利性。即我有通过它来循环使用为(;;)循环,以保持性能。 - 我以前写C code,其中每个循环是一个为(;;)。也许我已经成为被宠坏了。 - 如果我实现IEnumerable&LT; T&GT;然后我得到了相同的性能ReadOnlyCollection还&LT; T&gt;和这个类是没有用的。

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.

不知道如何实现的全部3个进球的完美结合:一个只读的完整性检查,没有性能的损失,以及方便的foreach()语法

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?

推荐答案

我觉得下面的你想要做什么。不过,我觉得其实这是不可取的。你堂堂一个不必要的和潜在的混乱抽象。是的,JIT可能会对其进行优化,最终,和你的同事应该流行起来。但你还是做一些语言并不意味着做。

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.

编辑:我已经调整,更好地解释了低于code,并提到了几个选项

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