【问题标题】:Initialization of static member objects c#静态成员对象的初始化c#
【发布时间】:2014-04-02 18:01:31
【问题描述】:

我在初始化静态成员对象时遇到了一些问题。在我的项目中有 3 个类文件:

FeatClass(RPG 风格而非 c# 类)和 Race

它们每个都有一些静态成员对象,例如Feat.General.MightyBlowRace.DwarfClass.Base.WarriorMightyBlow.GetType() -> FeatDwarf.GetType() -> RaceWarrior.GetType() -> Class。一个专长可以依赖于其他专长、职业和种族,职业和种族也是如此。这三个类别中的每一个都不是由真正的类/壮举/种族引用的,而是由一个可以在字典中查找的名称字符串引用,例如:Class someClass = Class.Implemented[someClassesName]

一些最小的例子:

public static Feat ArmorHeavy = new Feat(
    "ArmorHeavy",
    Req.Feats(ArmorLight.GetName),
);

public static Feat ArmorLight = new Feat(
    "ArmorLight",
    Req.Feats(),
);

如您所见,ArmorHeavy 首先需要ArmorLight 可用,并且该要求仅由ArmorLight 的名称(简单的字符串“ArmorLight”)标识。

我没有收到编译器错误,但是运行时我收到以下错误

NullReferenceException:对象引用未设置为对象的实例 专长+精通..cctor()

我认为在 ArmorHeavy 的初始化过程中,C# 到达了调用 ArmorLight.GetName 的位置,现在跳转到 ArmorLight 的初始化并在 ArmorLight 初始化后完成 ArmorHeavy。情况并非如此,因为如果我交换这两个成员对象的位置或删除需求,则不会出现错误。

我该如何解决这个问题?请不要告诉我,我必须相应地订购所有专长。

【问题讨论】:

  • 为什么ArmorHeavy 依赖于ArmorLight?大概它们都应该依赖于一些更抽象的Armor 类型,不是吗?
  • 我对 D&D 了解不多,但我认为如果不先获得轻型专长,就无法获得重型专长。

标签: c# static initialization static-members


【解决方案1】:

你必须这样做,不可能访问空引用的成员。

但是使用static constructor可以更清楚:

public static Feat ArmorHeavy;
public static Feat ArmorLight;

static ClassName()
{
    ArmorLight = new Feat("ArmorLight", Req.Feats());
    ArmorHeavy = new Feat("ArmorHeavy", Req.Feats(ArmorLight.GetName));
}

请注意,在static ClassName 中,ClassName 是类的真实名称,这些属性在 :) 中定义

另一种选择是将它们设为Lazy,但这对于仅仅避免正确的初始化顺序可能太麻烦了。

由于有很多这样的东西,将这些属性和依赖项移到代码之外可能是个好主意,例如移到 XML 中:

<Feats>
  <Feat Name="Light" />
  <Feat Name="Heavy" Requires="Light" />
</Feats>

然后编写一些代码来读取 XML 并初始化您的对象。

您的实际 XML(或其他格式)可能需要比这更复杂,因为可能需要多个依赖项等。

当然,这一切都取决于您的要求...

【讨论】:

  • 不可能使用静态构造函数,因为那只会让我拥有一个 Feat 实例。我希望所有专长都属于专长类型。
  • 一个非静态类可以有一个静态构造函数——不管你创建多少实例,它只会被执行一次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多