如何在结构体中初始化字符数组

6
如何在C#中初始化结构体中的char数组。我正在尝试这样做。
struct cell
{
    public char[] domain =new char[16];
    public int[] Peers;
    public int NumberOfPeers;
    public char assignValue;
}

但是它给出了一个错误,即我们不能在结构体的主体中初始化数组!有人能告诉正确方法吗?
7个回答

10
您可以使用构造函数。
struct cell
{
    public cell(int charArraySize) : this()
    {
         domain = new char[arraySize];
    }

    public char[] domain;
    public int[] Peers;
    public int NumberOfPeers;
    public char assignValue;
}

注意:即使使用结构体,也不应该有公共字段,而应该将它们封装在属性中。
而能够更改结构体的值则是一个更严重的问题 - 可变结构体很糟糕

1
“struct” 对象不能包含无参数的构造函数。 - e_ne
1
一个结构体如何拥有一个无参数的显式构造函数? - Jeppe Stig Nielsen
1
你对属性的理解是正确的,但根据Even和Jeppe的评论,这段代码实际上无法编译。 - Trevor Pilley
1
这段代码无法编译。结构体的实例构造函数必须分配结构体的所有实例字段。你可以通过实际赋值或“链接”(隐式)无参构造函数来“修复”它,如下所示: : this() - Jeppe Stig Nielsen
2
现在这个结构体是合法的(可以编译通过)。但它仍然是一个旨在可变的结构体。实际上,类型为intchar的“简单”字段只能通过对已经创建的cell值进行修改来使用。 可变的结构体通常会导致错误(特别是对于那些知识不足以初始化结构体的人,比如原始帖子中的人)。因此,在回答中提供有关可变结构体的警告可能是相关的。 - Jeppe Stig Nielsen
1
@JeppeStigNielsen:如果Peers的类型是数组,那么var thing1 = thing2; thing2.Peers[1]=9;将会在thing1.Peers[1]中存储9或者不写入任何内容到thing2.Peers[1]中,这很容易引起混淆,比暴露基本类型字段更加困难。实际上,我不确定如何使类似于thing1.Peers[1]=9;的操作在C#中像值类型数组一样运行,尽管在vb.net中可以进行等效操作。 - supercat

3
在 .NET 中,值类型的一个主要限制是它们无法包含数组,即使是固定大小的数组,除非离开托管代码领域(C# 提供了使用 "unsafe" 和 "fixed" 关键字在值类型中包含固定大小数组的方法,但使用该功能的代码将无法在某些安全上下文中使用)。它们可以包含对数组的引用,但如果复制包含数组引用的结构,则副本将接收与原始数组相同的数组引用。
虽然大多数情况下,一个结构类型最好完全公开其包含的内容(通过公共字段公开其整个状态),而不是假装成为与胶带粘合在一起的变量集合,但其状态应该封装可变类对象(例如 System.Array)的结构必须使用不同的模式。
如果一个结构体应该表现为具有 64 个浮点数的值类型数组,并且希望实际上将浮点数存储在 System.Array 中而不是在 64 个单独的字段中,则该结构体可能应该包含一个类型为 float[] 的私有字段 Arr。要读取元素 n,请检查 Arr 是否为空。如果是,则返回零。否则,返回 Arr[n] 的值。要写入元素 n,请设置临时变量 Arr2 为新的 float[64],并在 Arr 不为空时复制 Arr。然后将 Arr2[n] 设置为所需值,并用 Arr2 替换 Arr。请注意,一旦将 float[] 存储到 Arr 中,它将再次永远不会被写入。如果尝试写入结构体的第 5 个元素,则该结构体将接收一个具有正确值的新数组;旧数组的第 5 个元素将不受影响。因此,该结构体将表现为值类型数组应该具有的形式(除了写入它将比对普通数组的写入速度慢得多)。
如果类型需要一个大数组,则最好使用 float[][] 或 float[][][];例如,可以使用 16 个大小为 16 的数组来保存 4096 个元素。在这种情况下,写入元素需要生成/复制一个 float[16],一个 float[16][] 和一个 float[16][][];三个大小为 16 的小数组可能比两个大小为 64 的数组更好,几乎肯定比一个大小为 4096 的数组更好。

价值类型语义肯定很有用,但是如上所述,如果结构体包含数组,则结构体无法提供非常高效的方法。如果元素数量较小,则另一种设计方法是仅为每个元素设置一个字段,并使用索引属性访问器使用switch语句读取或写入结构体字段。这有点棘手,但对于小于十几个元素的结构体而言,几乎肯定比上述描述中使用数组更有效。


2

你可以使用类而不是结构体(尽管它有所区别,但你没有说明你将如何使用类型)。

或者你可以编写一个构造函数。但请注意,结构体实例的构造函数必须至少接受一个参数。

如果你坚持使用结构体,请确保将其设置为不可变的结构体。一种方法是将所有字段设置为readonly,然后在实例构造函数中对它们进行赋值。


1

1

您可以使用构造函数来实现此功能。请参考MSDN。

struct cell
{
    public cell(int size)
    {
         domain = new char[size];
         this.Peers = Peers;
         this.NumberOfPeers = NumberOfPeers;
         this.assignValue = assignValue;
    }    
}

1
一个结构体如何拥有一个无参数的显式构造函数? - Jeppe Stig Nielsen
@JeppeStigNielsen 没错,你说得对。它不能没有参数。已更新。 - Soner Gönül
看起来你接收了一个“in”参数(值参数),然后立即给你的参数分配了新的内容。这很令人困惑。还记得要分配所有字段。 - Jeppe Stig Nielsen
1
现在看起来你正在将最后三个字段分配给它们自己。但是这样不会编译,因为你试图读取未分配的字段。 - Jeppe Stig Nielsen

1

尝试使用类似这样的东西:

[StructLayout(LayoutKind.Sequential)]

public class TCardDB

{

public TCardDB(string strCardNo)

{

CardNo = strCardNo;

FName = LName = string.Empty;

OpenMode = FingerCount = 0;

Finger1 = new string[3];

Finger2 = new string[3];

}

..........

..........

}

0

对于char[]数组来说;

我们在处理字符数组时遇到了很多困难,但实际上我们可以轻松地添加一个字符串... 因为字符串本质上就是一个char[]数组... 并且具有您所需的所有索引功能。

这种方法对我很有效。


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