Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading a method in subclass (Enum vs int)

Why the following two code samples produce different output?

Case 1

enum EnumType
{
    First,
    Second,
    Third
}

class ClassB
{
    public string Func(int index)
    {
        return "Func(int)";
    }

    public string Func(EnumType type)
    {
        return "Func(EnumType)";
    }
}

class Program
{
    static void Main(string[] args)
    {
        ClassB b = new ClassB();
        Console.WriteLine(b.Func(0));
        Console.WriteLine(b.Func(EnumType.First));
        Console.ReadLine();
    }
}

Output:

Func(int)
Func(EnumType)

Case 2

enum EnumType
{
    First,
    Second,
    Third
}

class ClassA
{
    public string Func(int index)
    {
        return "Func(int)";
    }
}

class ClassB : ClassA
{
    public string Func(EnumType enumType)
    {
        return "Func(EnumType)";
    }
}

class Program
{
    static void Main(string[] args)
    {
        ClassB b = new ClassB();
        Console.WriteLine(b.Func(0));
        Console.WriteLine(b.Func(EnumType.First));
        Console.ReadLine();
    }
}

Output:

Func(EnumType)
Func(EnumType)

I am puzzled. Does it mean that Func(EnumType) hides Func(int) declared in the base? If this is the case then why literal 0 is implicitly casted to EnumType in the second case without a warning?

EDIT:

There is even more interesting behavior when I try

Console.WriteLine(b.Func(0));         
Console.WriteLine(b.Func(1));
Console.WriteLine(b.Func(EnumType.First));

What is your guess the output should look like?

here it is:

 Func(EnumType)
 Func(int)
 Func(EnumType)

Any ideas why 0 and 1 are treated differently?

EDIT 2:

It turns out that literal 0 indeed has special meaning in C#.

Here and here I found an excellent description of this behavior (see the accepted answers).

like image 415
alexm Avatar asked Jul 17 '12 04:07

alexm


1 Answers

Yes, it does hide the Func(int) declared in class A.

Furthermore, please see enum (C# Reference)

The default underlying type of enumeration elements is int

You might also want to have a look at Polymorphism (C# Programming Guide)

EDIT

If you ere to change

Console.WriteLine(b.Func(0));          
Console.WriteLine(b.Func(1)); 
Console.WriteLine(b.Func(EnumType.First)); 

to

int i = 0;
Console.WriteLine(b.Func(i));          
Console.WriteLine(b.Func(1)); 
Console.WriteLine(b.Func(EnumType.First)); 

you will find that the output should be

Func(int)   
Func(int)   
Func(EnumType)

It would seem that 0 is implicitly casted to the default enum value if passed directly to the function call.

EDIT 2

I checked the IL code and it does seem that it implicitly casts the 0 to an enum

IL_0000: nop
IL_0001: newobj instance void ClassB::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.0
IL_0009: callvirt instance string ClassB::Func(valuetype EnumType)
IL_000e: call void [mscorlib]System.Console::WriteLine(string)
IL_0013: nop
IL_0014: ldloc.0
IL_0015: ldc.i4.0
IL_0016: callvirt instance string ClassB::Func(valuetype EnumType)
IL_001b: call void [mscorlib]System.Console::WriteLine(string)
IL_0020: nop
IL_0021: call string [mscorlib]System.Console::ReadLine()
IL_0026: pop
IL_0027: ret
like image 67
Adriaan Stander Avatar answered Sep 22 '22 17:09

Adriaan Stander