I'm not sure if I'm using the right terms here. But I'm just thinking, if there is any major difference between assignment compatibility and type constraints. Let me explain it with code:
public class A {}
public class B : A {}
public class C : A {}
public static void Test(A a){}
public static void Test2<T>(T a) where T : A {}
From code above, is there any difference between Test and Test2? I can call both Test and Test2 with A or any of its derived types (B and C). But, how are they different to compiler? Does generic method somehow preserves the type such that if I call it with B it will not cast it to A, I tried experimenting with overload resolution but there seems to be no difference, please see my experiment with overload resolutions.
class Program
{
    public class A {}
    public class B : A {}
    public class C : A {}
    public static void Test(A a) { O(a); }
    public static void Test2<T>(T a) where T : A { O(a); }
    public static void O(A a) { Console.WriteLine("A"); }
    public static void O(B a) { Console.WriteLine("B"); }
    public static void O(C a) { Console.WriteLine("C"); }
    static void Main(string[] args)
    {
        Test2<A>(new A());
        Test2<B>(new B());
        Test2<C>(new C());
        Test(new A());
        Test(new B());
        Test(new C());
        Console.Read();
    }
}
Everything just prints out A. Can someone shed light on this, why would you use one over other?
 
     
     
    