在查看了这里的答案并在自己身上玩了一点之后,我提出了以下实现,它在运行时而不是编译时检查约束。
// This example takes 3 parameters...
public class GenericConstraint<T1, T2, T3>
{
public GenericConstraint(Type type)
{
if (!(type is T1) || !(type is T2) || !(type is T3))
{
throw new Exception("This is not a supported type");
}
}
}
现在我从我的自定义类继承了这个......
public class Custom<T> : GenericConstraint<string, int, byte>
{
public Custom() : base(typeof(T))
{
}
}
这现在会引发错误:
Custom<long> item = new Custom<long>();
这不!
Custom<byte> item2 = new Custom<byte>();
正如 Marc Gravell 所说,这不是对继承或泛型的良好使用。从逻辑上考虑,通过继承 GenericConstraint,这只是将继承限制在 this 上,并且也没有正确使用类型层次结构。就泛型的使用而言,这实际上是毫无意义的!
因此,我有另一种解决方案,它作为一种辅助方法来在运行时约束类型。这将对象从继承中释放出来,因此对类型层次结构没有影响。
public static void ConstrainParameterType(Type parameterType, GenericConstraint constraintType, params Type[] allowedTypes)
{
if (constraintType == GenericConstraint.ExactType)
{
if (!allowedTypes.Contains<Type>(parameterType))
{
throw new Exception("A runtime constraint disallows use of type " + parameterType.Name + " with this parameter.");
}
}
else
{
foreach (Type constraint in allowedTypes)
{
if (!constraint.IsAssignableFrom(parameterType))
{
throw new Exception("A runtime constraint disallows use of type " + parameterType.Name + " with this parameter.");
}
}
}
}
public enum GenericConstraint
{
/// <summary>
/// The type must be exact.
/// </summary>
ExactType,
/// <summary>
/// The type must be assignable.
/// </summary>
AssignableType
}
这现在允许对通用对象进行多种类型约束,即使类型是密封的等等。
“公共类 Custom where T : string ... 是不允许的,因为唯一符合条件的 T 是: string (字符串是密封的)——使它作为泛型毫无意义。”
是的,这是没有意义的,但是在某些情况下,您可能希望限制一个对象以允许,例如;字符串、StringBuilder 和 SecureString。虽然这不提供编译时约束,但它确实提供了运行时约束,以及可以在约束中使用哪些类型的一些灵活性。