【问题标题】:Returning a generic type with a base class constraint from a function without casting in C# [duplicate]从函数返回具有基类约束的泛型类型,而无需在 C# 中进行强制转换 [重复]
【发布时间】:2020-02-04 15:33:16
【问题描述】:

我正在用 Unity 编写一个游戏,其中有许多不同种类的物品可以放在玩家的物品栏中。有一个基类 ItemSettings,它具有所有项目包含的属性,然后是枪支、组件、盔甲等的一级派生类型。所有项目都由一个枚举值唯一标识,我有一个类来管理该类的字典enum => 项目的设置。

基本类层次结构:

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# 泛型系统的一些细微差别。

【问题讨论】:

  • 基本上可以参考这个线程C# Generic Method, cannot implicit convertTItemType在编译时是未知的
  • TItemTypeItemSettings,但反过来不一定正确。编译器只知道itemSettingItemSettings,而不是它恰好具有所需的返回类型。

标签: c# generics


【解决方案1】:

您的调用代码如下所示:

GunSettings setting = Get<GunSettings>(item);

但是如果 item 是 Component 而不是 Gun 呢?然后它不能被投射到GunSetting。显式转换是必需的,因为虽然可能知道该函数将始终获取正确子类型的 ItemSettings 实例,但编译器却不知道。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    相关资源
    最近更新 更多