如何解决如何在C#中创建一个包含数组但不使用堆的结构?
我需要什么:
- 具有任意数量的顶点(或至少达到
max
个顶点数量)的多边形 - 它应该是一个结构,以便它可以快速运行并可以按值分配/传递
似乎我不能使用数组或集合来存储顶点,因为那样我的多边形结构将指向堆上的对象,并且当一个多边形按值分配给另一个多边形时,将仅执行浅拷贝,并且我会让两个多边形都指向同一个顶点数组。例如:
Polygon a = new Polygon();
Polygon b = a;
// both polygons would be changed
b.vertices[0] = 5;
然后我如何创建一个可以具有任意数量(或某个固定数量)的顶点,却完全不使用堆的结构?
我可以只使用很多变量,例如v1,v2,v3 ... v10
等,但是我想或多或少地保持代码的整洁。
解决方法
您可以选择使用fixed
关键字定义数组,并将其放入堆栈中。
但是除非您处于unsafe
上下文中并使用指针,否则您不能直接访问数组的元素。
要获得以下行为:
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;
}
}
需要考虑的几件事。上面的代码需要使用
unsafe
选项进行编译。MaxSize
也是常数,并且所需的存储空间不能超过该值。我正在使用索引器this[int]
来访问元素(而不是字段),并且还具有使用ToArray()
转换为本机数组的方法。构造函数还可以采用本机数组,也可以使用空数组初始化值。这是为了确保例如new FixedArray(10)
将在固定数组中初始化至少10个值(而不是未定义,因为它是默认值)。
详细了解fixed
from Microsoft的用法或搜索C# Fixed Size Buffers
。
-
堆数组字段
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` } }
如果适合您的逻辑,则可以使用Span<T>
,它在堆栈中分配。了解更多here
另一种使用复制构造函数复制数组的方法
public Polygon(Polygon other)
{
this.vertices = other.vertices.Clone() as int[];
}
然后
var a = new Polygon();
a.vertices[0] = 5;
var b = new Polygon(a):
Debug.WriteLine(a.vertices[0]);
// 5
Debug.WriteLine(b.vertices[0]);
// 5
b.vertices[0] = 10;
Debug.WriteLine(a.vertices[0]);
// 5
Debug.WriteLine(b.vertices[0]);
// 10
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。