Restrict generic T to specific types

I have the following method:

public static IResult<T, String> Validate<T>(this T value) {
} // Validate

      

How to constrain T as Int16, Int32, Int64, Double and String?

+3


source to share


3 answers


You cannot restrict generics in this way, you can only choose one class as a restriction. You have to either do 5 overloads or find an interface, all 5 of which share and use that. Which option you choose will depend on what the Validate

doe is.

This is how you will do overloading.

public static IResult<Int16, String> Validate<T>(this Int16 value) {
} // Validate

public static IResult<Int32, String> Validate<T>(this Int32 value) {
} // Validate

public static IResult<Int54, String> Validate<T>(this Int64 value) {
} // Validate

public static IResult<double, String> Validate<T>(this double value) {
} // Validate

public static IResult<String, String> Validate<T>(this String value) {
} // Validate

      



Here, using the common interface, all the members you enumerate do IConvertible

so you can restrict this, however this will allow any IConvertible not just the list you specified.

public static IResult<T, String> Validate<T>(this T value) where IConvertible {
} // Validate

      

+2


source


You can only do this:

public static IResult<T, String> Validate<T>(this T value) where T: int
{
    //validate
} 

      



Only classes and interfaces can be used as a constraint.

+4


source


Such restrictions are not available for generics. The closest you can get from generics to what you want to achieve is to add the following constraints:

public static IResult<T, String> Validate<T>(this T value) 
    : where T IConvertible, IComparable, IComparable<T>, IEquatable<T>
{
    // Validate
}

      

All primitive types implement these interfaces. For further restriction, the only option is to check the type at runtime and throw an exception if it doesn't match:

Type type = typeof(T);
if (type != typeof(Int16) &&
    type != typeof(Int32) &&
    type != typeof(Int64) &&
    type != typeof(Double) &&
    type != typeof(String))
{
    throw new ArgumentException();
}

      


This is not the nicest solution, but at least it will give you some compilation time and runtime safety.

+2


source







All Articles