1

Let's say I create a generic method, and implement some types, like shown in the code below. I also have two objects, a Foo and a Bar, where Bar inherits from Foo.

I then implement the generic method for Foo.

If I call the method with Bar, why doesn't it hit the Foo overload of the method?

I tested the code below and that's what it returns. I am more interested in why that happens.

My question raises because I want to process Bet and Bar the same way, so the body of the method would be the same. Although, I cannot see how to do this without either duplicating the code, or creating another method that dispatches to the correct one.

public class Foo 
{
}

public class Bar : Foo
{
}

public class Bet : Foo
{
}

public static void Test(Foo foos)
{
    Console.WriteLine("You hit Test(Foo)");
}

public static void Test<T>(T generic)
{
    Console.WriteLine("You hit Test<T>");
}

void Main()
{
    Foo foo = new Foo();
    Bar bar = new Bar();
    Bet bet = new Bet();
    
    Test(foo);  // Prints "You hit Test(Foo)", as expected 
    Test(bar);  // Prints "You hit Test<T>", I expexted "You hit Test(Foo)"
    Test(bet);  // Prints "You hit Test<T>", I expexted "You hit Test(Foo)"
}
  • 1
    Because the generic method creates a new method with the *exact* type, so it's a better match than the method with the parent type – Panagiotis Kanavos Jun 28 '19 at 08:27
  • 1
    Why would it hit `List`? `List` and `List` aren't compatible. Try `List a = new List();` to see what I mean. – ProgrammingLlama Jun 28 '19 at 08:27
  • 1
    Indeed, using `int` and `object` is a bad example. `object` is *not* the parent type of `int`. Even if it were, `List` is not the parent type of `List`, it's a different type entirely – Panagiotis Kanavos Jun 28 '19 at 08:30
  • An example that actually demonstrates the question would be two methods that accept types A and B, with B inheriting from A: `Test(T generic)` and `Test(A a)`. Even then, the generic method will be picked because it matches the type exactly. – Panagiotis Kanavos Jun 28 '19 at 08:35
  • Thanks guys, apologies for the misleading code - I amended that to match the question – Eduardo Pignatelli Jun 28 '19 at 08:55

1 Answers1

3

The code doesn't match the question. First of all, object is not the parent of int. Value types have to be boxed to be converted to object. Even with reference types, assuming A is the parent of B, List<A> is not the parent of List<B>. List<A> creates a new type that has no inheritance relation to List<B>.

An example that actually demonstrates the question would be :

class A    {    }

class B:A  {    }

static string Test<T>(T generic)
{
    Console.WriteLine("T - generic overload");
    return "Generic overload";
}

static string Test(A a)
{
    Console.WriteLine("A - A overload");
    return "A overload";
}

static string Test(object o)
{
    Console.WriteLine("object - objectoverload");
    return "object overload";
}


void Main()
{
    var b =new B() ;
    var a=new A() ;

    Test(b);
    Test(a);
}

The output would be :

T - generic overload
A - A overload

The generic overload creates an exact match for B which means it's a better fit than Test(A)

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236