In object-oriented languages that support generic type parameters (also known as class templates, and parametric polymorphism, though of course each name carries different connotations), it is often possible to specify a type constraint on the type parameter, such that it be descended from another type. For example, this is the syntax in C#://for classes:class ExampleClass<T> where T : I1 {}//for methods:S ExampleMethod<S>(S value) where S : I2 {        ...}What are the reasons to use actual interface types over types constrained by those interfaces? For example, what are the reasons for making the method signature I2 ExampleMethod(I2 value)?
What is the reason of using an interface versus a generically constrained type
object oriented;type systems;generics
Using the parametric version givesMore information to the users of the functionConstrains the number of programs you can write (free bug checking)As a random example, suppose we have a method which calculates the roots of a quadratic equationint solve(int a, int b, int c) {  // My 7th grade math teacher is laughing somewhere}And then you want it to work on other sorts of number like things besides int. You can write something likeNum solve(Num a, Num b, Num c){  ...}The issue is that this doesn't say what you want it to. It says Give me any 3 things that are number like (not necessarily in the same way)   and I'll give you back some sort of numberWe can't do something like int sol = solve(a, b, c) if a, b, and c are ints because we don't know that the method is going to return an int in the end! This leads to some awkward dancing with downcasting and praying if we want to use the solution in a larger expression.Inside the function, someone might hand us a float, a bigint, and degrees and we'd have to add and multiply them together. We'd like to statically reject this because the operations between these 3 classes is going to be gibberish. Degrees are mod 360 so it won't be the case that a.plus(b) = b.plus(a) and similar hilarities will arise.If we use the parametric polymorphism with subtyping we can rule all this out because our type actually says what we mean<T : Num> T solve(T a, T b, T c)Or in words If you give me some type which is a number, I can solve equations with those coefficients.This comes up in a lot of other places as well. Another good source of examples are functions which abstract over some sort of container, ala reverse, sort, map, etc.