I heard about constraints on generic types today and immediately had to investigate. I am not sure how this has made it through my radar, but I am glad that I found it today.
tldr; Constraints inform the compiler about the capabilities a type argument must have. Without a constraint the compiler will allow any Type T to be passed, which is System.Object. As an alternative we can add a constraint that says where T : class which will allow the compiler and intellisense to know that only the type = class will be accepted.
Adding a constraint on a generic type can significantly reduce the amount of bugs that are present in an application by adding type casting to a generic while still allowing the generic to be generic. I believe to explain this I need to give an example.
Say we have a class "Employee" shown below. This class is simple enough and has a constructor, a name, and an ID which are set on creation.
Now say we want to create a generic method that acts on any employee, or class that has a Name/ID combination and we do not want to write the method multiple times. We could instead do something like below.
Now I know on the surface this does not look like much because we could accomplish the same thing with the following code, but not using a generic type.
Now is where you can see the true power of a constraint in action. Say we create another class called Manager which also has a Name and an ID and we want our EmployeeList to do the same thing on a manager. Using the snippet above we could not do this without duplicating code because EmployeeList only accepts a class Employee. Instead if we modify the constraint we can now act on Manager and Employee while still disallowing all other types of classes that would result in an error.
The change is very subtle, but by adding Manager to the where statement we now have a generic method that can act on the Employee and Manager class while disallowing all other types we know to cause errors.
A complete list of where statements are below.
<base class name>