Проблема в том, что поскольку ваше свойство не является статическим, компилятор не знает, что все они возвращают одно и то же значение.Поскольку ваш UniformInt
не запечатан, другой пользователь может унаследовать его и переопределить GlslType
, чтобы вернуть что-то еще.Тогда UniformInt
и все производные классы могут быть использованы для вашего GetCode<T>()
метода.
Статический метод действительно будет лучшим вариантом.Чтобы убедиться, что вы реализуете их во всех классах (то, что вы не можете форсировать, потому что статические методы не могут быть абстрактными), я бы написал простой модульный тест, который использует отражение, чтобы загрузить все классы, наследуемые от Uniform<T>
, и проверить, если ониопределите статическое свойство.
ОБНОВЛЕНИЕ
Размышляя о том, как атрибуты могут помочь, и после некоторых экспериментов я придумал следующее.Это определенно не выиграет конкурс красоты, но как учебное упражнение это было полезно;)
using System;
using System.Linq;
namespace StackOverflow
{
internal class StackOverflowTest
{
private static void Main()
{
string sInt = UniformInt.GlslType;
string sDouble = UniformDouble.GlslType;
}
}
public abstract class Uniform<B, T> // Curiously recurring template pattern
where B : Uniform<B, T>
{
public static string GlslType
{
get
{
var attribute = typeof(B).GetCustomAttributes(typeof(GlslTypeAttribute), true);
if (!attribute.Any())
{
throw new InvalidOperationException(
"The GslType cannot be determined. Make sure the GslTypeAttribute is added to all derived classes.");
}
return ((GlslTypeAttribute)attribute[0]).GlslType;
}
}
}
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
internal sealed class GlslTypeAttribute : Attribute
{
public string GlslType { get; private set; }
public GlslTypeAttribute(string glslType)
{
GlslType = glslType;
}
}
[GlslType("int")]
public class UniformInt : Uniform<UniformInt, int> // Curiously recurring template pattern
{
}
[GlslType("double")]
public class UniformDouble : Uniform<UniformDouble, double> // Curiously recurring template pattern
{
}
}