Why can't I use System.ValueType as a generics constraint?

C#Generics

C# Problem Overview


  • Why can't I use a constraint of where T : System.ValueType?
  • Why does Microsoft prevent this type from being a constraint?

Example:

Why can't I do the following?

// Defined in a .Net class
public void bar<T>(T a) where T : ValueType {...}

// Defined in my class
public void foo<T>(T a) where T : ValueType 
{ bar<T>(a); }

What is the difference in using struct over ValueType?

// Defined in my class
public void foo<T>(T a) where T : struct 
{ bar<T>(a); }

C# Solutions


Solution 1 - C#

There are two differences between using

where T : struct

and

where T : ValueType
  • the latter would allow T to be ValueType itself, which is a reference type.
  • the latter would also allow T to be a nullable value type

The first of these differences is almost never what you want. The second could occasionally be useful; Nullable<T> is slightly odd in that it satisfies neither the where T : struct nor where T : class constraint.

More useful would be the constraint

where T : struct, System.Enum

which is prohibited by C# for no good reason that I can tell. See my blog post and the Unconstrained Melody project for more on this.

Solution 2 - C#

ValueType is not the base class of value types, it is simply a container for the value when it is boxed. Since it is a container class and not in any sort of hierarchy for the actual types you're wanting to use, it is not useful as a generic constraint.

Solution 3 - C#

Using struct as a generic constraint is functionally equivalent to a "ValueType" constraint. In .NET, a struct is a value type.

Solution 4 - C#

I think the example below covers a lot of use cases that one would expect from ValueType. The parameter type of T? allows nullables, and the type constraints restrict it to structs that implement IFormattable which is true for the common value types I can think of.

public void foo<T>(T? a) where T : struct, IFormattable

Note that this allows types such as decimal, datetime, timespan.

https://docs.microsoft.com/en-us/dotnet/api/system.iformattable?view=netcore-3.1

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionzfedoranView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Rex MView Answer on Stackoverflow
Solution 3 - C#bobbymcrView Answer on Stackoverflow
Solution 4 - C#VoteCoffeeView Answer on Stackoverflow