У меня интересная проблема.Я хотел бы создать универсальный класс, который может работать как с ссылочными типами, так и с типами Nullable<T>
.В основном я хочу что-то вроде:
public class ClassWithNull<T>
{
public T varName = null;
}
Теперь это, конечно, не компилируется, потому что не всем типам может быть присвоено значение NULL, а именно типы значений, не допускающие значения NULL.Но проблема в том, что Nullable<T>
является типом значения, поэтому простое добавление where T : class
мне не поможет.Мой generics-foo не слишком силен, но я не смог найти способа сказать, что T
должен быть либо ссылочным типом, либо типом значения NULL.
Идея, которую я должен решить, состоит в том, чтобы сделать ClassWithNull<T>
абстрактным классом.Затем я мог бы добавить два подкласса, один для работы со ссылочными типами, а другой - для типов значений, допускающих значение NULL.Затем статический метод фабрики в базовом классе может использовать отражение, чтобы определить, какой подкласс должен быть создан.Примерно так:
public static ClassWithNull<T> CreateClassWithNull<T>()
{
StackTrace st = new StackTrace();
Type type = st.GetFrame(1).GetMethod().GetGenericArguments()[0];
if (!type.IsValueType)
{
return new ClassWithReferenceType<T>();
}
else if (type == typeof(Nullable))
{
return new ClassWithNullableValueType<T>();
}
else
{
throw new Exception("Must provide nullable type.");
}
}
Проблема здесь в том, что генерики разрешаются статически.Если ClassWithReferenceType<U>
ожидает, что U
будет ссылочным типом, то вызов new ClassWithReferenceType<T>()
в фабричном методе является ошибкой компиляции, поскольку T
не обязательно должен быть ссылочным типом.Компилятор не знает о проверке времени выполнения.
Есть идеи о том, как реализовать такую вещь?