11

I have the following method:

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

How can I restrict T to be Int16, Int32, Int64, Double and String?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Miguel Moura
  • 36,732
  • 85
  • 259
  • 481
  • 3
    Probably by creating a non-generic method with 5 overloads for those types. There's no way of restricting a generic method that specifically at compile time. – Charles Mager Jun 13 '15 at 14:33
  • 1
    possible duplicate of [Is there a constraint that restricts my generic method to numeric types?](http://stackoverflow.com/questions/32664/is-there-a-constraint-that-restricts-my-generic-method-to-numeric-types) – Trevor Pilley Jun 13 '15 at 14:34

3 Answers3

11

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 constraint.

Sjoerd222888
  • 3,228
  • 3
  • 31
  • 64
6

You can't restrict generics in that way, you can only choose a single class as a constraint. You must either make 5 overloads or find a interface all 5 of those things share and use that. Which option you choose will depend on what Validate doe.

Here is how you would do the overloads.

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<Int64, 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 is by using a common interface, all of the members you list Implement IConvertible so you could restrict by that, however this will allow any IConvertible not just the 5 you listed.

public static IResult<T, String> Validate<T>(this T value) where IConvertible {
} // Validate
Rudu
  • 15,682
  • 4
  • 47
  • 63
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
5

Constraining a generic to a set of specific types is not available. But other types of constraints are. The closest you can get with 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 the primitive types implement these interfaces. To further restrict, 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 isn't the nicest solution, but at least it will give you a bit of compile time and runtime safety.

zcoop98
  • 2,590
  • 1
  • 18
  • 31
Jaanus Varus
  • 3,508
  • 3
  • 31
  • 49