首页 > 解决方案 > 如何处理结构内的数组?

问题描述

我正在寻找一种方法来用我的项目中的数组替换我的一些 List 对象以提高性能。原因是我要替换的列表不会经常更改大小(有时只更改一次),因此将它们与数组交换是有意义的。另外,我想尽可能地防止堆上的分配。

所以我的想法是创建一个包含两个成员“Count”和“Array”的结构(ArrayStruct)。该结构将具有一些函数来添加/删除/获取/设置/等...数组中的元素。计数将保持数组中可用元素的计数,并且数组只会增加大小,永远不会减少。请注意,这是针对一个非常特殊的情况,因为我知道数组大小不会很大。

我遇到的主要问题是,当我将对已经存在的 ArrayStruct 对象(在示例中命名为 a)的引用传递给另一个(在示例中命名为 b)时 - 我可以在其中编辑数组,但是一旦我在 a 中调整它的大小,我在 b 中得到一个超出范围的异常。这是因为我通过 更新引用的方式System.Array.Resize,所以对象 b 不知何故不归因于这种变化?

我唯一能想到的想法是尝试覆盖赋值运算符,以便它会在赋值时创建一个新数组......但显然这不起作用。

我的 ArrayStruct

    public struct ArrayStruct<T>
    {
        [SerializeField] private int m_Count;
        [SerializeField] private T[] m_Array;

        public int Count => m_Count;

        public void Initialize(int startSize)
        {
            m_Count = 0;
            m_Array = new T[startSize];
        }

        public T GetAt(int index)
        {
            return m_Array[index];
        }

        public void SetAt(int index, T newValue)
        {
            m_Array[index] = newValue;
        }

        public void Add(T newElement)
        {
            if (m_Array == null) {
                m_Array = new T[1];
            } else if (m_Array.Length == m_Count) {
                System.Array.Resize(ref m_Array, m_Count + 1);
            }

            m_Array[m_Count] = newElement;
            m_Count++;
        }

        public void Remove(T element)
        {
            for (int i = 0; i < m_Count; ++i) {
                if (!element.Equals(m_Array[i])) {
                    continue;
                }

                for (int j = index; j < m_Count - 1; ++j) {
                    m_Array[j] = m_Array[j + 1];
                }
                m_Count--;
                m_Array[m_Count] = default(T);
                break;
            }
        }

        //Trying to overload the = operating by creating a auto cast, this gives a compile error
        /*public static implicit operator ArrayStruct<T>(ArrayStruct<T> otherArray)
        {
            var newArray = new ArrayStruct<T>();
            newArray.m_Count = otherArray.Count;
            newArray.m_Array = new T[otherArray.Length];
            otherArray.m_Array.CopyTo(newArray.m_Array);
            return newArray;
        }*/

一个展示问题的例子

var a = new ArrayStruct<string>()
a.Add("hello");
var b = a;
print (b.GetAt(0)); //"hello"

a.SetAt(0, "new value for a");

print(b.GetAt(0));//"new value for a"  , changing a changed b because the array is the same in both, this is bad

a.Add("resizing array");
print (b.GetAt(1)); //"Out of range exception" ,  because the array was resized for a but not for b therefore the connection broke

那么,当我将结构分配给另一个变量时,你们中的任何人都知道如何制作一个新的数组副本吗?当然,我知道我可以使用一个函数来做这样的事情 b = new ArrayStruct(a); 但我希望它是隐含的。或者,如果有一种方法可以阻止对我也有用的分配。var a = new ArrayStruct();//让这个工作 var b = a; //防止这种情况发生

如果您有任何其他解决方案可以方便地用数组替换列表,请告诉我

标签: c#

解决方案


那么,当我将结构分配给另一个变量时,你们中的任何人都知道如何制作一个新的数组副本吗?当然,我知道我可以使用一个函数来做这样的事情 b = new ArrayStruct(a); 但我希望它是隐含的。

你不能那样做。如果a是一个结构并且你执行var b = a,那么它将总是设置b为 ; 的浅拷贝a。没有办法改变这种行为。

做类似的事情b = new ArrayStruct(a)是你能做的最好的。


推荐阅读