有没有办法让泛型类型约束也泛型?

时间:2020-07-10 06:36:39

标签: c# unity3d generics

我正在尝试创建一个通用容器类以包含通用类型列表,但是我无法在c#中用语法表示它。

此代码使用了一些游戏引擎API(Unity),因此可能有助于忽略ScriptableObject,SerializedField或我需要扩展通用类开头的原因。

这是我的代码:

public class RankUnlockedItemBase<T> : ScriptableObject
{
    [SerializeField] private int acquiredRankPoints;
    public int AcquiredRankPoints { get => acquiredRankPoints; }
    [SerializeField] private T item;
    public T Item => item;

    public bool IsUnlocked(int rankPoints)
    {
        return rankPoints > acquiredRankPoints;
    }
}

这是实现的样子:

public class RankUnlockedInt : RankUnlockedItemBase<int> { }

这是我从中派生问题的通用容器类。类型约束为通用类型RankUnlockedItemBase的通用RankUnlockedItemContainer:

public class RankUnlockedItemContainer<T> : ScriptableObject where T : RankUnlockedItemBase<?> // Im lost here
{
    [SerializeField] private List<T> items;
    public List<T> Items {get => items; }

    public List<T> GetAllUnlockedItemsUpToRank(int rank)
    {
        List<T> unlockedItems = new List<T>();
        for (int i = 0; i < items.Count; i++)
        {
            if (items[i].IsUnlocked(rank))
            {
                unlockedItems.Add(items[i]);
            }
        }

        return unlockedItems;
    }
}

这就是我想实现的目标

public class RankUnlockedIntContainer : RankUnlockedItemContainer<RankUnlockedInt> { }

2 个答案:

答案 0 :(得分:2)

是的,您可以有两种通用类型

                -> backGround UIView full screen  (with alpha 0.3) 
   MainPopUpView 
               -> popUpView short & centre and shows actual content

并实施例如

public abstract class RankUnlockedItemContainer<TItem, TValue> : ScriptableObject : where TItem : RankUnlockedItemBase<TValue> { ... }

答案 1 :(得分:2)

使用两个通用类型参数。一个TList用于您的列表,另一个Titem用于该类型的RankUnlockedItemBase

public class RankUnlockedItemContainer<TList, TItem> : ScriptableObject where TList : RankUnlockedItemBase<TItem> {}

当然,您可以显式导出容器类型。

public class RankUnlockedIntContainer : RankUnlockedItemContainer<RankUnlockedInt, int> {}

但是,如果您不更改除具体类型之外的实现,则可以实例化容器而无需派生子类型。想想List<T>,为什么要为每种项目类型派生一个类型?

var container = new RankUnlockedItemContainer<RankUnlockedInt, int>();