【发布时间】:2013-03-02 03:35:04
【问题描述】:
我猜这是一个哲学问题。
我们正在启动一个视频游戏项目,并在开发过程中发现了 C#。我们需要的第一件事就是将常量存储在一堆数组中,这样任何人都可以轻松访问这些值,因此我们可以在定义新角色或武器类型时快速添加或修改值。
现在在 C++ 中,我学会了这样做:
- 在一些 constants.h 文件中声明一个枚举,其最后一个元素是“WHATEVER_TYPE_END”;
- 声明大小为“WHATEVER_TYPE_END”的常量数组,因为枚举和数组索引在 C++ 中运行良好;
- 用 constants.cpp 中不同类型的各种值填充这些数组。
一个例子:
enum FoulType {
FOUL_TYPE_NONE,
FOUL_TYPE_OUT_OF_PLAY,
FOUL_TYPE_OFFSIDE,
FOUL_TYPE_VIOLENCE,
FOUL_TYPE_RETENTION,
FOUL_TYPE_END
};
extern const char* FoulTypeNames[FOUL_TYPE_END];
extern const float FoulSanctionChances[FOUL_TYPE_END];
extern const ushort FoulSanctionSeconds[FOUL_TYPE_END];
extern const uchar FoulSanctions[FOUL_TYPE_END];
它很简洁,因为它让程序员可以毫不费力地检索修饰符。如果我想计算我的角色会造成多少伤害,我会这样做
CharacterType charType = myCharacter.getType();
WeaponType weapType = myCharacter.getWeapon().getType();
damage = CharacterDamages[ charType ] * WeaponModifiers[ weapType ];
现在在 C# 中,我一直在努力思考如何获得类似的结果。经过三个小时的游历,我终于有了一些实用的东西,但它看起来有点 hackish。
我拥有的是一个静态类(命名为常量),其中声明了公共枚举,并定义了大小为 (int)SomeEnum.END 的公共静态只读数组。声明如下:
public enum WeaponType
{
Gun = 0,
Shotgun,
Assault,
End
};
public static readonly int[] WeapDamage = new int[ (int)WeaponType.End]
{
10,
50,
10
};
由于CS0134,数组是只读的而不是常量。枚举必须显式转换为 int,否则它可以正常工作。现在,我知道那些“常量”并不是真正的常量,这些数组的值可能会改变;对于这个问题,我找到了两种可能的解决方案:
- 保护数组,并使用 getter,如果有人真的需要整个数组而不仅仅是一个值,则返回数组的副本;
- 使用 ReadOnlyCollection
由于我偏向于我的旧 C++ 方式(它们本身可能不像我想像的那么干净),这些解决方案都不吸引我(尤其不是 ReadOnlyCollection,因为我(我猜主要是迷信) ...) 害怕时间和/或内存开销(我们正在处理实时多人游戏)。
我想,大多数情况下,我担心我所付出的努力只是为了用另一种语言实现与我所知道的几乎相似但不完全一样的东西,这表明我做事不正确. 那么,对于比我有更多 C# 和/或视频游戏制作经验的人来说,在这里存储一堆常量的正确方法是什么?
【问题讨论】:
-
为什么武器类型的所有属性都分布在未连接的数组中?为什么不使用 WeaponType 结构或类来聚合每种武器类型的属性?
-
+2 用于在同一个句子中使用“peregrinations”和“functionnal”[原文如此]。
-
@Eric 实际上这就是 OP 在他的 C# 示例代码中使用的内容。另一个代码是 C++ 示例。