如何在C#中创建包含数组但不使用heap的结构?
我需要的是:如何在C#中创建包含数组但不使用heap的结构?,c#,memory,struct,heap,C#,Memory,Struct,Heap,我需要的是: 具有任意数量顶点(或至少达到max顶点数)的多边形 它应该是一个结构,这样它可以很快,并且可以通过值进行赋值/传递 似乎我不能使用数组或集合来存储顶点,因为这样我的多边形结构将指向堆上的对象,当一个多边形按值指定给另一个多边形时,将只执行浅复制,并且我将使两个多边形都指向同一个顶点数组。例如: Polygon a = new Polygon(); Polygon b = a; // both polygons would be changed b.vertices[0]
- 具有任意数量顶点(或至少达到
顶点数)的多边形max
- 它应该是一个结构,这样它可以很快,并且可以通过值进行赋值/传递
Polygon a = new Polygon();
Polygon b = a;
// both polygons would be changed
b.vertices[0] = 5;
那么,我如何创建一个可以有任意数量(或固定数量)顶点的结构,但根本不使用heap
我可以使用很多变量,比如
v1、v2、v3。。。v10
等,但我希望或多或少保持代码干净。如果符合您的逻辑,您可以使用堆栈上分配的Span
。阅读更多使用复制构造函数复制数组的另一种方法
public Polygon(Polygon other)
{
this.vertices = other.vertices.Clone() as int[];
}
然后
您可以选择使用
fixed
关键字定义数组,从而将其放入堆栈中
但是您不能直接访问数组的元素,除非您处于不安全的上下文中并使用指针
要获得以下行为:
static void Main(string[] args)
{
FixedArray vertices = new FixedArray(10);
vertices[0] = 4;
FixedArray copy = vertices;
copy[0] = 8;
Debug.WriteLine(vertices[0]);
// 4
Debug.WriteLine(copy[0]);
// 8
}
然后使用以下类定义:
public unsafe struct FixedArray
{
public const int MaxSize = 100;
readonly int size;
fixed double data[MaxSize];
public FixedArray(int size) : this(new double[size])
{ }
public FixedArray(double[] values)
{
this.size = Math.Min(values.Length, MaxSize);
for (int i = 0; i < size; i++)
{
data[i] = values[i];
}
}
public double this[int index]
{
get
{
if (index>=0 && index<size)
{
return data[index];
}
return 0;
}
set
{
if (index>=0 && index<size)
{
data[index] = value;
}
}
}
public double[] ToArray()
{
var array = new double[size];
for (int i = 0; i < size; i++)
{
array[i] = data[i];
}
return array;
}
}
堆栈数组字段
struct StdArray
{
int[] vertices;
Foo(int size)
{
vertices = new int[size];
}
}
unsafe struct FixedArray
{
fixed int vertices[100];
int size;
Foo(int size)
{
this.size = size;
// no initialization needed for `vertices`
}
}
您真正关心的是堆栈与堆
还是引用类型与值类型
?如果是前者,请检查。将一个潜在的大多边形完全放在堆栈内存中并将其传递(每次将其作为函数参数传递时复制它等)并不一定比使用标准集合更快(甚至可能更慢)。您是否有需要修复的实际问题,或者您是否正在尝试先发制人地优化一个可能根本不存在的问题?我觉得在这种情况下,您的问题更多地是关于深度复制列表,而不是关于堆栈与堆。堆栈和堆是实现细节,99%的时候我们都不需要担心。另外,请参见:恕我直言,如果您解释您想要做什么,您可能会得到更好的答案。你的问题是怎么做。请回答你的问题。请记住,C#/Roslyn编译器技术在优化代码和处理数据结构方面做得非常出色。如果您需要比它更聪明,您可能确切地知道它在为您做什么,您应该告诉我们。过早的优化可能会使代码完全无法维护。修复对象不会将其移动到堆栈中,也不会使其表现为值类型。它只是确保GC在其收集过程中不会移动它。@Servy实际上不会,fixed
in structures是一个特殊的关键字,用于移动堆栈中的值。我简化了示例并删除了fixed()
语句,它仍然有效。自那以后,情况有所改善。试试看,你会发现这完全符合要求。据我所知,“fixed”关键字将固定大小的数组作为结构的一部分嵌入。数组位于堆栈还是堆上取决于结构的使用方式。如果它被用作局部变量声明,那么实际上,数据将存在于堆栈上,但是如果它被用作引用类的成员,那么缓冲区将存在于堆上(类的一个实例将整个固定大小的数组作为其字段的一部分嵌入,而不是作为对独立数组的引用)因此,使用类Foo{FixedArray data;}
的声明,数据可能驻留在堆上。这是有道理的,因为结构的要点是将所有数据保存在一起。
unsafe struct FixedArray
{
fixed int vertices[100];
int size;
Foo(int size)
{
this.size = size;
// no initialization needed for `vertices`
}
}