当结构体包含一个数组/列表时,创建一个结构体的数组/列表。

3

我是一名C程序员,对于C#还不熟悉,因此在选择最佳方法时遇到了麻烦。希望能得到一些建议以帮助我作出决策。
我有一个结构体(在C语言中定义),看起来像这样:

struct structData
{
    long type;
    long myArray[50];
    string text;
}

我创建了一个这些结构体的数组,可以全局/公开地持续读写它们。(我需要在其中存储数据,以便稍后访问)
structData arrayOfStructs[50];  

目标是像这样访问数据:

arrayOfStructs[0].type = 123;
arrayOfStructs[0].myArray[0] = 456;

当我尝试在C#中实现时,我遇到了各种错误:
"myArray"需要设置为50,但它需要在不安全的区域内
如果我尝试初始化它"... = new ...",我会收到一个错误
首先,我应该使用List<>而不是数组吗?是否有性能差异?
其次,我应该创建一个类而不是结构体,在构造函数中初始化数组,然后创建对象的列表/数组吗?您将如何实现此操作?
是的,我需要使用long类型。

请将以下与编程��关的内容从英语翻译成中文。仅返回已翻译的文本:发布数组的其余代码,包括初始化。 - smartcaveman
5
仅仅因为语法相似,并不意味着你应该在C#中编写C代码。 - ChaosPandion
1
我并不是在尝试用C#写C,我只是在说如果用C来做的话我会怎么做,而不是应该怎么做。这就是为什么我问应该怎么做。 - Nick Sinas
3个回答

4
public class StructData
{
    public long type;
    public long[] myArray = new long[50];
    public string text;
}

StructData[] datas = new StructData[100];

for (int i = 0; i < datas.Length; i++)
{
    datas[i] = new StructData();
}

使用类来处理大型对象,使用结构体来处理小型的、可能是不可变的“对象”(假设结构体应该是小的并且不可变的。但它们可以按照您的要求定义)。
需要明确的是,在 .NET 中,我所知道的最大的结构体是由 4 个 int 组成的(即 Guid)。我认为这是衡量小型和大型结构体的一个好基准。
如果需要扩展集合,请使用 List,如果大小固定,请使用数组,List 的速度不比数组慢多少(它们在内部使用数组实现)。我不知道有没有人对数组和 List 进行过性能基准测试。通常情况下,List 使用的内存略多于数组,因为它会保留一些空间来扩大集合(还会保留 List 的当前大小和指向内部数组的指针,以及其他数据。因此,List 至少会增加一个 int 和一个指针的大小,再加上所有对象的 std 开销)。您可以通过向构造函数传递要保留的元素数量来“预设”List 的大小。

当我尝试写入数组时,出现错误。我使用了这一行代码:datas[0].type = 123; - Nick Sinas
@Nick 你需要初始化数据的单个元素。StructData[] datas = new StructData[100]; 初始化了数组(容器),但你需要初始化单个元素。我已经在示例中添加了相应的代码行。 - xanatos

2
所以,首先要说的是,你应该避免在C#中编写C代码。除了明显的语法相似性外,这两种语言几乎没有什么共同之处。
在C#中,你很少使用结构体。结构体的语义与类的语义不同。以下是何时使用结构体和何时使用类的快速概述。有更多的资源可用,我只是选择了第一个看起来合理的主题结果:何时使用结构体 其次,是的,尽可能使用通用容器类型。性能不会成为问题,并且在长期运行中它会让你的生活变得更加轻松。你声明数组的语法有误(与C不同),应该是:
long[] myArray = new long[50];

如果您需要将数组固定在内存中以实现互操作性,可以通过使用 fixed 关键字来实现,但是当您将托管数组传递给本机函数时,互操作层实际上会为您执行此操作。

我建议您花些时间从基础开始学习C#,并忘记语法与C类似的事实。它们是完全不同的语言,具有完全不同的语义和最佳实践。


0
如果您需要本地互操作性,也就是说,您将通过某种机制或仅仅是在字节数组周围进行转换来传递这些类型,则需要使用不安全/固定的内容,并且可以像这样完成。
unsafe struct structData 
{     
    int type;
    fixed int myArray[50]; // long is 64-bit in C# was that intentional?
    string text; // string is a managed type
}

如果你是从C语言转到C#,那么你绝对不应该直接将C代码翻译成C#等效代码,因为这样做没有多大意义。在C#中,事物是被管理的,你通常会接受与托管代码相关的成本,并且一开始并不考虑性能影响。

一个好的起点是学习C#的内存模型,因为它解释了值类型和引用类型之间微妙但重要的差异。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接