C # Воспитание от родового типа родового типа класса? Слишком сложно для меня, чтобы сформировать более подходящий вопрос к проблеме: | - PullRequest
0 голосов
/ 23 октября 2019

У меня проблемы с выяснением, как я могу использовать универсальные типы для решения моей проблемы. Также я не знаю, как описать мою проблему вкратце, поэтому я сделаю упрощенную версию своей проблемы как расширенное объяснение.

Я создаю систему для переключения качества, перехода уровней качества между различными типами «компонентов»класс. У меня есть базовый класс, такой как:

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"

Конечно, в моей системе происходит больше, это просто очень упрощенная версия, чтобы определить мой вопрос: как я могу избежать кастования классов, как я могу сделать это правильно? Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...