Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to restrict T to value types using a constraint?

Tags:

I want to restrict the possible types N can take-on using a constraint. I wish to restrict N to be either a int or a decimal.

public static Chart PopulateInto<T, N>(List<T> yAxis, List<N> xAxis) where N : int, decimal {     // Do stuff here } 

Any help appreciated...

like image 812
Prisoner ZERO Avatar asked Nov 05 '10 19:11

Prisoner ZERO


People also ask

How do you specify a constraint for the type to be used in a generic class?

It will give a compile-time error if you try to instantiate a generic type using a type that is not allowed by the specified constraints. You can specify one or more constraints on the generic type using the where clause after the generic type name.

Which keyword is used to apply constraints on type?

Object, you'll apply constraints to the type parameter. For example, the base class constraint tells the compiler that only objects of this type or derived from this type will be used as type arguments.

What is the purpose of the interface constraint on a type parameter?

Interface Type Constraint You can constrain the generic type by interface, thereby allowing only classes that implement that interface or classes that inherit from classes that implement the interface as the type parameter.


2 Answers

It's not possible to constrain a generic parameter to a specific value type.

You can however force it to be a value type or struct by adding where N : struct, but that's all.

like image 119
Pieter van Ginkel Avatar answered Oct 19 '22 14:10

Pieter van Ginkel


Unfortunately, it is not possible to specify generic type constraints that only allow specific value types. More to the point, it wouldn't make much sense even if it was allowed.

You're allowed to specify a class as a generic constraint but this is because you can inherit from classes, the constraint thus sets the minimum threshold of what types you're allowed to use.

If this was allowed for value types, where you cannot inherit from those types, you would effectively limit yourself to only that type.

Thus you cannot do this, but you have a few alternatives:

  • You can declare it without the constraint, and handle the problem at runtime. I would not recommend this way
  • You can declare overloads that take the specific types you're interested in.

    Since you only have two such types this is what I would recommend doing.

Here are the overloads you would declare:

public static Chart PopulateInto<T>(List<T> yAxis, List<int> xAxis) {     // Do stuff here }  public static Chart PopulateInto<T>(List<T> yAxis, List<decimal> xAxis) {     // Do stuff here } 

Now, additionally, if your handling of those values doesn't really rely on the numeric quality of those types, you just want to limit which types you can handle, then you can always declare your original method as well, privately, and call this method from your overloads. This would still limit your code to only allowing int or decimal, publicly, but your implementation would still be generic. Without knowing exactly what "Do stuff here" entails it is impossible to tell if this is a viable option or not but here is the code anyway:

public static Chart PopulateInto<T>(List<T> yAxis, List<int> xAxis) {     return PopulateInto<T, int>(yAxis, xAxis); }  public static Chart PopulateInto<T>(List<T> yAxis, List<decimal> xAxis) {     return PopulateInto<T, decimal>(yAxis, xAxis); }  private static Chart PopulateInto<T, N>(List<T> yAxis, List<N> xAxis) where N : struct {     // Do stuff here } 
like image 28
Lasse V. Karlsen Avatar answered Oct 19 '22 15:10

Lasse V. Karlsen