C#中的泛型类型参数约束



考虑以下泛型类:

public class Custom<T> where T : string
{
}

这会产生以下错误:

"字符串"不是有效的约束。用作约束的类型必须可以是接口、非密封类或类型参数。

是否有其他方法来约束泛型类可以使用哪些类型?

此外,我可以约束到多个类型吗?

例如

T只能是字符串、int或字节

public class Custom<T> where T : string

是不允许的,因为只有T满足以下条件:string(stringsealed)-这使得它作为泛型毫无意义。

此外,我可以约束到多个类型吗?

否-除非您在运行时通过反射而不是在约束中这样做(静态构造函数是实现这一点的一种方法-如果使用不正确,则抛出异常)

T can only be string, int or byte

可能使用类似IEquatable<T>的东西,但这并没有像您希望的那样限制它,所以最终:没有。

可以通过过载的工厂访问它:

public abstract class Custom
{
public static Custom Create(int value)
{ return new CustomImpl<int>(value); }
public static Custom Create(byte value)
{ return new CustomImpl<byte>(value); }
public static Custom Create(string value)
{ return new CustomImpl<string>(value); }
private class CustomImpl<T> : Custom
{
public CustomImpl(T val) { /*...*/ }
}
}

根据我的经验,我想说我理解你为什么想要stringint。。。因为泛型基类具有字符串或int 类型的ID

但可以肯定的是,这是不可能的。正如msdn的描述所说:http://msdn.microsoft.com/en-us/library/d5x73970%28v=vs.80%29.aspx

我们可以有一个约束class(类似字符串的引用对象)或struct(类似int的ValueType)所以混合字符串和int是不可能的

注意:字符串的错误是有意义的,因为字符串是密封的,所以它不必是通用的-string ID是我们需要的

在回顾了这里的答案,并对自己进行了一些尝试之后,我提出了以下实现,它在运行时而不是编译时检查约束。

// 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");
}
}
}

现在我从我的Custom类继承了这个。。。

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,这将继承仅限于此,并且没有正确使用类型层次结构。就泛型的使用而言,这实际上是毫无意义的!

因此,我有另一个解决方案,它作为一个辅助方法在运行时约束类型。这将对象从继承中释放出来,因此对类型层次结构没有影响。

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,其中不允许使用T:string…,因为唯一符合条件的T是:字符串(字符串是密封的)-使其作为一个泛型,相当没有意义。">

是的,这毫无意义,但在某些情况下,您可能希望约束对象以允许;String、StringBuilder和SecureString。虽然这不提供编译时约束,但它确实提供了运行时约束,以及可以在约束中使用哪些类型的一些灵活性。

最新更新