Quick Tour of C# Generic Type Constraints 
Tags: csharp, deepdive, nuggets
Published: 2019-08-02 14:41:10

[Last time](https://dev.to/daneb/quick-tour-of-generics-in-c-2fea) we looked at some fundamentals to Generics. Let's peel a little more of the onion regarding Generics and consider Type Constraints.

> A _Type Constraint_ is the restriction imposed on a type used by a generic. 

```csharp
public class AGenericClass<T> where T : IComparable<T> { } ...
public class UsingEnum<T> where T : System.Enum { } ...
public class GenericList<T> where T : Employee ...
``` 

Constraints inform the compiler about the capabilities a type argument must have by restricting it. Without any constraints, the type argument could be any type. Imposing the constraint/s on the generic _increases the number of allowable operations and method calls to those supported by the constraining type and all types in its inheritance hierarchy_.

### Clarification

So if I had a wooden drawer, it could pretty much take anything. In fact, it would most likely be very difficult to order things and keep things in their place. And with the continual opening and closing of the drawer, one is also unlikely to efficiently access their papers, pens, rulers, stapler etc.
![Drawer](http://www.stevesshelves.com/wp-content/uploads/2012/06/Logo.png)
But assume we have a drawer compartmentalized by inner linings of wood. All of a sudden, things have a place and are more structured in terms of access. And this is what Type constraints do. They impose restrictions to provide a more human and safe interface to the Generic type - \<T\>.

![Seven Constraints](https://raw.githubusercontent.com/daneb/dev.to/master/7constraints.png)

There are 7 constraints one could consider when using a Generic, so let's review a few to get an idea of how to use them.

### Value Type Constraint
```csharp
where T : struct
```
This constrains the type argument to a value and not a reference type.
Examples of what would be *valid*:
 + Votes\<int\>
 + UploadedFiles\<FileMode\>

Examples of what would be *invalid*:
 + Swap\<object\>
 + ReportContent\<StringBuilder\>

### Reference Type Constraint
```csharp
where T : class
```
This constrains the type argument to be a reference type and not a value type.
Examples are simply the reverse of what we just saw in the **Value Type Constraint**. That is, the type argument \<T\> can be any class, interface, array or delegate.

### Constructor Type Constraint
```csharp
where T : new()
```
This constrains the type argument to have a public parameter-less constructor. 

*snip taken from [C# in Depth](https://csharpindepth.com/)*
```csharp
public T CreateInstance<T>() where T : new()
{
   return new T();
}
```
This methods returns a new instance of whatever type you specify, constrained of course by the fact that the type must have no parameters in its constructor. This is a useful constraint when working with the [Factory Method Design Pattern](https://sourcemaking.com/design_patterns/factory_method).

### Sample Using Interface Constraint

{% gist https://gist.github.com/daneb/10751c5c0d0cb22d1e0168c71c41fc92 %}

In the sample above, we see the creation of a rudimentary [Tuple](https://docs.microsoft.com/en-us/dotnet/csharp/tuples). The type _MyTuple_ has an *interface type constraint*. Thus the type argument must be or implement [IEquatable](https://docs.microsoft.com/en-us/dotnet/api/system.iequatable-1?view=netframework-4.8) .

When developing our _MyTyple_; **IEquatable** enforces the following constraints: 
1. You must implement it's method - Equals(\<T\>)
2. And you should override the base class implementations of Equals(Object) and GetHashCode() so that their behaviour is consistent with that of the Equals(\<T\>) method.

There are four main generic interfaces for comparisons, two of them **IComparer\<T\>** and **IComparable\<T\>** are about comparing values and for ordering. That is, one value \<=, =\> or == too another.

The other two, **IEqualityCompare\<T\>** and **IEquatable\<T\>** are used for comparing two items for equality to some criteria and applying a hash of an item.

The consumer of the code is constrained by a contract that describes the bounds of the generic. So while the generic is supportive of variations of a kind (or type) it is prescriptive around what it should do or be capable off.

### Last words
Generic type constraints are nothing more then the restrictions imposed on generic types preventing abuse, but also clearly communicating the constraints for its use and providing compile-time errors.

#### For more depth, please see the resource below:
1. [Introduction to IEquatable](https://www.c-sharpcorner.com/article/story-of-equality-in-net-part-three/)
2. [You must implement Equal and HashCode](https://blogs.msdn.microsoft.com/jaredpar/2009/01/15/if-you-implement-iequatablet-you-still-must-override-objects-equals-and-gethashcode/)
3. [IEquality Interface](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.iequalitycomparer-1?view=netframework-4.8)
4. [Why use constraints?](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters#why-use-constraints)