.net - .NET 中的只读数组

标签 .net arrays readonly

数组是一种迭代无序项集的快速方法,并且通常最好将它们设为只读。虽然使用“readonly”关键字公开数组是没有用的,因为数组的内容仍然可以更改,但 ReadOnlyCollection 包装器解决了这个问题。问题是在我所做的测试中它比普通数组慢 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() 语法的便利性。 IE。我必须使用 for(;;) 循环对其进行迭代才能保持性能。 -- 我曾经编写 C 代码,其中每个循环都是一个 for(;;)。也许我已经被宠坏了。 -- 如果我实现 IEnumerable,那么我将获得与 ReadOnlyCollection 相同的性能,并且该类毫无用处。

知道如何实现所有 3 个目标的完美结合:只读健全性检查、无性能损失以及方便的 foreach() 语法吗?

最佳答案

我认为下面的内容可以满足您的要求。然而,我认为这实际上是不可取的。您强加了不必要且可能令人困惑的抽象。是的,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();
    }
}

关于.net - .NET 中的只读数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/953289/

相关文章:

c# - 使用 LINQ 在对象列表中分组来执行聚合

.net - 如何查明我的 WCF 服务器何时退出(并关闭它的 TCP 连接)

ruby - 初学者数组迭代和错误代码解释

javascript - 在React中动态创建多级下拉菜单并获取下拉菜单中选定子菜单的值

java - 如何改变这个矩阵螺旋遍历的方向和起点?

.net - 构建自定义 "ClaimsAuthorizationManager"Windows Identity Foundation 类的好方法是什么?

c# - 使用 XmlSerializer 将 xml 元素反序列化为数组不起作用

Winforms - 如何控制复选框颜色(类似于只读文本框)

report - 自由办公基地;以只读方式打开报告

.net - 为什么 ReadOnlyCollection<T> 不是 ReadOnlyList<T>?