将派生的 classes 存储在基础 class 字典中

Storing derived classes in a base class Dictionary

我正在尝试创建一个场景或状态管理器,它为每个状态存储一个字典,作为加载或更改程序状态(例如,主菜单状态和游戏状态)的一种方式。我有一堆派生的 classes of base class State,其中包含未包含在 base State class 中的变量。我可以安全地将它们存储在该词典中吗?我会丢失任何数据吗?如果这不起作用,有哪些替代方法可以实现我的目标?

这似乎是您可以轻松测试的内容。但只是为了好玩,假设你有一个基础 class 像:

public class Base
{
    public string Name
    {
        get;
        set;
    }

    public override string ToString()
    {
        return Name;
    }
}

和派生的 class 如:

public class Derived : Base
{
    public string Description
    {
        get;
        set;
    }

    public override string ToString()
    {
        return base.ToString() + " - " + Description;
    }
}

然后你可以像这样创建一个设置:

Base baseObject = new Base{ Name = "Base"};
Derived derivedObject = new Derived { Name = "Derived", Description = "Description" };

Dictionary<int, Base> dictionary = new Dictionary<int, Base>();
dictionary.Add(1, baseObject);
dictionary.Add(2, derivedObject);

现在你可以运行做个小测试,看看是否有信息丢失:

foreach (Base value in dictionary.Values)
{
    Console.WriteLine(value.ToString());
}

如您所见,不仅调用了正确的覆盖 ToString(),而且它仍然具有 Description 属性 的正确值。所以不,你没有 "lose" 任何东西。但是只要是base类型,就只能直接访问base属性。

顺便说一句。您还可以检查一个值是否确实 is 某个派生类型:

foreach (Base value in dictionary.Values)
{
    if (value is Derived)
    {
        Console.WriteLine("{0} is Derived", value.Name);
        // trying to access value.Description at this point
        // would cause a compiler error "Cannot resolve symbol".
    }
    else
    {
        Console.WriteLine("{0} is not Derived", value.Name);
    }
}

并且使用 as 并检查是否为 null,您可以 "safely"(例如,无一例外地由直接强制转换引起)获取 "full" 派生类型中的值,其中您可以再次访问所有其他属性:

foreach (Base value in dictionary.Values)
{
    Derived derived = value as Derived;
    if (derived != null)
    {
        Console.WriteLine("{0} is Derived and has Description: {1}",
                           derived.Name, derived.Description);
        // now that derived actually is of type Derived,
        // accessing derived.Description is perfectly fine.
    }
}