我发布此答案是为了响应您在乔的回答中详细说明我的评论的请求。
第一点:如果您my_data_t
出于某种原因需要成为结构,C# 确实支持这些。除非您愿意,否则您不必像 Joe 那样将其升级到类。
public struct MyData
{
public string Description;
public uint ColourID;
public uint Quantity;
}
这是一个可变结构。给定这个结构的一个实例,如果我愿意,我可以修改它的值。大多数人会说可变结构是邪恶的。作为游戏开发者,我想说可变结构非常重要,但也很危险。
任何对象的可变字段和属性都可以使用对象初始化器语法进行初始化,这可能最类似于您在 C 中所做的事情:
MyData x = { Description = "Brown Bear", ColourID = 0x88, Quantity = 10 };
我个人认为这有点笨拙,特别是对于大型结构,但如果您想使用它,它是可用的。
readonly
您可以通过向其字段添加修饰符来将结构更改为不可变:
public struct MyData
{
public MyData(string description, uint colourID, uint quantity)
{
this.Description = description;
this.ColourID = colourID;
this.Quantity = quantity;
}
public readonly string Description;
public readonly uint ColourID;
public readonly uint Quantity;
}
请注意,readonly
这只防止对象引用被更改。如果对象是可变的,它不会阻止对象本身发生变异。
另请注意,我还添加了一个构造函数。这是因为readonly
字段只能在静态初始化程序或对象的构造函数内部设置(除非有一些技巧)。MyData
在这里,您将在 Joe 的回答中初始化 as 的新实例:
MyData x = new MyData("Brown Bear", 0x88, 10);
第二点:恒常性,或缺乏恒常性。C# 不支持 C-style constness,因为 C-style constness is broken。Eric Lippert 曾是 Microsoft C# 语言团队的一名开发人员,他在此处详细阐述了这一点。
我认为,除非你真的、真的、真的有充分的理由,否则不用担心模拟 C 风格的 constness 会好得多。一致性最终是一种防止您的代码被恶意或无知者篡改的方法。不管你喜欢与否,恶意软件都能够改变你的数据——在 C 和 C# 中——我们有一个更好的工具来保护自己免受他人的无知:封装!
将使用该表的功能包装在一个类中,使该表成为该类的私有成员,然后不要改变它。如果在某些时候您确实需要将该表暴露给外界,那么您可以ReadOnlyCollection
按照 Joe 的建议使用:
public static readonly ReadOnlyCollection<MyData> ReferenceTable = new ReadOnlyCollection<MyData>(new []
{
new MyData(/* whatever */),
new MyData(/* whatever */),
new MyData(/* whatever */),
});
ReadOnlyCollection
只是其他一些集合的薄包装,在这种情况下,您的数据表。它可以包装任何实现IList<T>
接口的对象,包括数组和一些内置集合。
还有一点需要注意:在您的一条评论中,您提到const
在 C 中声明表的原因之一是因为它会影响对象在内存中的分配位置。这不是这里的情况。在上面的例子中,RefData
会在托管堆上声明,因为它是一个数组,而数组是引用类型。