【问题标题】:Storing and indexing constants in C#在 C# 中存储和索引常量
【发布时间】: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# 和/或视频游戏制作经验的人来说,在这里存储一堆常量的正确方法是什么?

【问题讨论】:

  • 为什么武器类型的所有属性都分布在未连接的数组中?为什么不使用 Wea​​ponType 结构或类来聚合每种武器类型的属性?
  • +2 用于在同一个句子中使用“peregrinations”和“functionnal”[原文如此]。
  • @Eric 实际上这就是 OP 在他的 C# 示例代码中使用的内容。另一个代码是 C++ 示例。

标签: c# arrays constants


【解决方案1】:

它真的必须是常数吗?我的意思是你可以把它包装在一个类中。我不喜欢使用大量依赖于其他常量的常量。您的代码不是很面向对象或可读性。当然,如果内存使用等是一个问题,也有例外。

但是做这种事情的 C# 方式是 OO。

public class Weapon {
  public string Name { get; private set; }
  public WeaponType Type { get; private set; }
}

public class WeaponType {
  public string Name { get; private set; }
  public int Damage { get; private set; }
}

等等

然后有一个工厂方法在开始游戏时初始化你的武器/角色等。实际数据可以像文件一样存储在任何地方。

【讨论】:

    【解决方案2】:

    我建议使用某种“数据存储”:数据库、文本文件、电子表格,无论您喜欢什么,都在启动时加载。这使得测试各种参数组合就像在数据库或文本文件等中编辑一行一样简单,无需重新编译。游戏稳定后,将这些作为资源存储在 EXE 中。

    【讨论】:

      猜你喜欢
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      • 2014-09-04
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      相关资源
      最近更新 更多