我有一个有趣的问题。我想创建一个通用类,既可以处理引用类型,也可以处理Nullable<T>
类型。基本上我想要这样的东西:
public class ClassWithNull<T>
{
public T varName = null;
}
现在这段代码当然不能编译,因为不是所有类型都可以赋值为null,即非可空值类型。但问题在于
Nullable<T>
是值类型,所以仅添加where T:class
无法解决问题。我的泛型知识不太牢固,但我找不到任何方法来表达T
必须是引用类型或可空值类型之一的要求。我想解决这个问题的方法是将
ClassWithNull<T>
变为抽象类。然后,我可以添加两个子类,一个用于处理引用类型,另一个用于处理可空值类型。然后,在基类中使用静态工厂方法并通过反射来确定应该构建哪个子类。类似以下内容: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
是引用类型。编译器不知道运行时检查。有没有关于如何实现这样一件事的想法?
x
是可空类型时,T x = null;
才会编译通过,但T x = default(T)
和x == null
将始终编译通过(对于非可空类型,它只返回false)。 - Gabetypeof(Nullable)
引用了一个与您所想不同的类型,即一个非泛型的静态类。可以使用type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)
来代替。在这种特殊情况下的另一种选择是Nullable.GetUnderlyingType(type) != null
。另外,请注意您可以使用typeof(T)
而不是您称之为的type
。 - Jeppe Stig Nielsen