У меня проблемы с выяснением, как я могу использовать универсальные типы для решения моей проблемы. Также я не знаю, как описать мою проблему вкратце, поэтому я сделаю упрощенную версию своей проблемы как расширенное объяснение.
Я создаю систему для переключения качества, перехода уровней качества между различными типами «компонентов»класс. У меня есть базовый класс, такой как:
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"
Конечно, в моей системе происходит больше, это просто очень упрощенная версия, чтобы определить мой вопрос: как я могу избежать кастования классов, как я могу сделать это правильно? Спасибо!