首页 > 解决方案 > 泛型类的泛型类型的 C# 育儿?对我来说太复杂了,无法对问题形成更合适的问题:|

问题描述

我无法弄清楚如何使用泛型类型来解决我的问题。另外我不知道如何简短地描述我的问题,所以我将简化版本的问题作为扩展解释。

我正在制作用于切换质量的系统,在不同类型的“组件”类之间转换质量级别。我有像这样的基类:

public abstract class QualityLevel_Base
{
    public bool Enabled = true;

    public virtual void Transition(QualityLevel_Base a, QualityLevel_Base b, double value)
    {
        if (value >= 1) Enabled = b.Enabled; else if (value <= 0) Enabled = a.Enabled;
    }

    protected static double Lerp(double a, double b, double t) { return (1 - t) * a + t * b; }
}

然后我像这样继承它:

public sealed class QualityLevel_LightSource : QualityLevel_Base
{
    public double Intensity;
    public double Range;
    public int ShadowsQuality;

    public override void Transition(QualityLevel_Base a, QualityLevel_Base b, double value)
    {
        QualityLevel_LightSource la = a as QualityLevel_LightSource; // One part of my problem - avoid casting
        QualityLevel_LightSource lb = b as QualityLevel_LightSource;

        base.Transition(a, b, value);
        Intensity = Lerp(la.Intensity, lb.Intensity, value);
        /* etc... */
    }
}

然后我想管理其他类中的质量级别,并能够将设置应用于所需的组件类。所以我有基类来管理任何质量级别:

public abstract class QualityManager_Base
{
    public Component SourceComponent { get; protected set; }
    public List<QualityLevel_Base> QualityLevels { get; protected set; }

    public virtual void Initialize(Component component, int qualityLevelsCount)
    {
        QualityLevels = new List<QualityLevel_Base>();
        SourceComponent = component;
        AutoQualitySettings(qualityLevelsCount);
    }

    public virtual void AutoQualitySettings(int qualityLevelsCount) { }

    public virtual void ApplyQualitySettings(QualityLevel_Base qualityLevel) 
    {
        SourceComponent.Enabled = qualityLevel.Enabled;
    }
}

我为 LightSource 继承了它,例如:

public sealed class QualityManager_LightSource : QualityManager_Base
{
    public LightSource Light { get; private set; }

    public override void Initialize(Component component, int qualityLevelsCount)
    {
        LightSource light = component as LightSource; // Another situation when I would like to avoid casting
        Light = light;
        base.Initialize(light, qualityLevelsCount);
    }

    public override void AutoQualitySettings(int qualityLevelsCount)
    {
        for (int i = 0; i < qualityLevelsCount; i++)
        {
            QualityLevel_LightSource lightSettings = new QualityLevel_LightSource();
            lightSettings.Intensity = Light.Intensity;
            lightSettings.Range = Light.Range;
            lightSettings.ShadowsQuality = i / qualityLevelsCount;
            if (i == qualityLevelsCount - 1) lightSettings.Enabled = false;
        }
    }

    public override void ApplyQualitySettings(QualityLevel_Base qualityLevel)
    {
        base.ApplyQualitySettings(qualityLevel);

        // To my Question: I want to use generic type to avoid casting
        QualityLevel_LightSource lightSettings = qualityLevel as QualityLevel_LightSource; 

        Light.Intensity = lightSettings.Intensity;
        Light.Range = lightSettings.Range;
        Light.ShadowsQuality = lightSettings.ShadowsQuality;
    }
}

实际上,我设法在这个问题上使用了泛型类型,例如:

public abstract class QualityLevel_Base<T> where T : QualityLevel_Base<T> { /*...*/ }

public class QualityLevel_LightSource : QualityLevel_Base<QualityLevel_LightSource> { /*...*/ }

public abstract class QualityManager_Base
{
    public List<QualityLevel_Base> QualityLevels; // Would like to define it like that but I have to do it 
    // like that:
public abstract class QualityManager_Base<T> where T : QualityLevel_Base<T>
{
    public List<QualityLevel_Base<T>> QualityLevels;
}

然后做这样的事情会导致错误:

public abstract class QualityManager_Base<T> where T : QualityLevel_Base<T>
{
    public List<QualityLevel_Base<T>> QualityLevels;

    public virtual void AddComponentForQualityManager(Component comp)
    {
        if (QualityLevels == null) QualityLevels = new List<QualityLevel_Base<T>>();

        LightSource light = comp as LightSource;
        if (light != null)
        {
            QualityManager_LightSource lightManager = new QualityManager_LightSource();
            QualityLevels.Add(lightManager); // Then I Can't do this because: "cannot convert from 'QualityManager_LightSource' to 'QualityLevel_Base<T>' "
        }

        /* ... */
    }
}

“无法从 'QualityManager_LightSource' 转换为 'QualityLevel_Base'”

我的系统中当然还有更多事情要做,它只是一个非常简化的版本来定义我的问题:我怎样才能避免强制转换类,我怎样才能正确地做到这一点?谢谢!

标签: c#genericsinheritance

解决方案


推荐阅读