Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphic methods not working on C# 4

I just stumbled over a very interesting problem. Giving the following code:

using System;

class Program
{
    class A { }
    class B : A { }

    private static void MyMethod(A a) /* first method */
    {
        Console.WriteLine("A"); ;
    }

    private static void MyMethod(B b) /* second method */
    {
        Console.WriteLine("B");
    }

    static void Main(string[] args)
    {
        var a = new A();
        // Call first method
        MyMethod(a);

        A b = new B();
        // Should call the second method
        MyMethod(b);

        Console.ReadLine();
    }
}

I would expect that the second method will be called because the runtime type of the variable is B. Any ideas why the code calls the first method instead?

Thanks, Tibi

Some clarifications: Polymorphism means several forms which has nothing to do where you declare the method.

Method overloading is a form of polymorphism, ad-hoc polymorphism.

The way polymorphism is normally implemented by using late binding.

dynamic is the workaround for this problem.

The fact is that this is not working in C#(or Java) it is a design decission which I would like to understand why was made, and none of the answers is answering this question.

/Tibi

like image 609
Tibi Avatar asked Nov 15 '11 18:11

Tibi


2 Answers

This isn't an example of polymorphism at all. Polymorphism comes in to play when you call methods ON the object, not when the object is used as a parameter. This is just a simple example of method overloading.

You declared b as being of type A, so the compiler is going to link to the overload that uses type A. The linker doesn't care that B is a subclass of A, it just picks the overload with the closest signature to the declared types (not the actual types) of the parameters passed in.

if you want to force it to use the 2nd method, cast b in to type B in the method call.

MyMethod((B)b);
like image 142
Bradley Uffner Avatar answered Nov 01 '22 14:11

Bradley Uffner


Method overloading in C#, by default, is determined statically at compile time. Since you are passing a statically typed variable of type A, it will statically bind to method with the A overload. Use the dynamic keyword to get the behavior you want.

static void Main(string[] args)
{
    dynamic d = new A();
    // Call first method
    MyMethod(d);

    d = new B();
    // Call the second method
    MyMethod(d);

    Console.ReadLine();
}
like image 33
jbtule Avatar answered Nov 01 '22 13:11

jbtule