从函数返回具有基类约束的泛型类型而无需在C#中进行强制转换

时间:2020-02-04 15:33:16

标签: c# generics

我正在Unity中编写一款游戏,其中包含很多可以在玩家清单中使用的物品。有一个基类ItemSettings,它具有所有项目都包含的属性,然后是枪,零件,装甲等的一级派生类型。所有项目都由枚举值唯一标识,我有一个类来管理该字典枚举=>项目的设置。

基本类层次结构:

class ItemSettings {
  public Item itemIdenfitier;
  public ItemCategory itemCategory;
}

class GunSettings : ItemSettings {...}

class ComponentSettings: ItemSettings {...}

这是为所有ItemSettings类型维护词典的单例类,并且是允许调用者检索特定项目设置的函数:

    public static TItemType Get<TItemType>(Item item) where TItemType : ItemSettings
    {
        ItemSettings itemSetting;
        switch (Instance.itemCategoryMap[item])
        {
            case ItemCategory.Gun:
                itemSetting = Instance.gunMap[item];
                break;
            case ItemCategory.Component:
                itemSetting = Instance.componentMap[item];
                break;
            default:
                throw new ArgumentOutOfRangeException($"Item category not found for item {item}");
        }

        return (TItemType) itemSetting;
    }

我不明白为什么我必须以这种方式进行转换,而不是像这样自己返回字典值:

    public static TItemType Get<TItemType>(Item item) where TItemType : ItemSettings
    {
        switch (Instance.itemCategoryMap[item])
        {
            case ItemCategory.Gun:
                return Instance.gunMap[item];
            case ItemCategory.Component:
                return Instance.componentMap[item];
            default:
                throw new ArgumentOutOfRangeException($"Item category not found for item {item}");
        }
    }

我得到了错误:

Cannot implicitly convert type GunSettings to TItemType

但是,TItemType具有必须为ItemSettings的约束,该约束应适用于GunSettings。我一定想念C#泛型系统的细微差别。

1 个答案:

答案 0 :(得分:2)

您的调用代码如下:

GunSettings setting = Get<GunSettings>(item);

但是,如果物品是一个组件而不是一把枪怎么办?然后就无法将其投放到GunSetting。进行显式转换是必需的,因为虽然可能知道该函数将始终获取正确子类型的ItemSettings实例,但编译器却不会。