views:

2269

answers:

3

I have the following VB.net interface that I need to port to C#. C# does not allow enumerations in interfaces. How can I port this without changing code that uses this interface?

Public Interface MyInterface

    Enum MyEnum
        Yes = 0
        No = 1
        Maybe = 2
    End Enum

    ReadOnly Property Number() As MyEnum

End Interface
+13  A: 
public enum MyEnum
{
    Yes = 0,
    No = 1,
    Maybe = 2
}

public interface IMyInterface
{
    MyEnum Number { get; }
}
Alexander Kojevnikov
This breaks the code that is using the interface. I would like to avoid that if possible.
A: 

What Alex said, he beat me to the punch.

Anders
+8  A: 

In short, you can't change that interface without breaking code, because C# can't nest types in interfaces. When you implement the VB.NET versions's interface, you are specifying that Number will return a type of MyInterface.MyEnum:

class TestClass3 : TestInterfaces.MyInterface
{

    TestInterfaces.MyInterface.MyEnum TestInterfaces.MyInterface.Number
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

}

However, since C# can't nest types inside interfaces, if you break the enumerator out of the interface, you will be returning a different data type: in this case, MyEnum.

class TestClass2 : IMyInterface
{

    MyEnum IMyInterface.Number
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

}

Think about it using the fully qualified type name. In the VB.NET interface, you have a return type of

MyProject.MyInterface.MyEnum

In the C# interface, you have:

MyProject.MyEnum.

Unfortunately, code that implements the VB.NET interface would have to be changed to support the fact that the type returned by MyInterface.Number has changed.

IL supports nesting types inside interfaces, so it's a mystery why C# doesn't:

.class public interface abstract auto ansi MyInterface

{ .property instance valuetype TestInterfaces.MyInterface/MyEnum Number { .get instance valuetype TestInterfaces.MyInterface/MyEnum TestInterfaces.MyInterface::get_Number() }

.class auto ansi sealed nested public MyEnum
    extends [mscorlib]System.Enum

{ .field public static literal valuetype TestInterfaces.MyInterface/MyEnum Maybe = int32(2)

    .field public static literal valuetype TestInterfaces.MyInterface/MyEnum No = int32(1)

    .field public specialname rtspecialname int32 value__

    .field public static literal valuetype TestInterfaces.MyInterface/MyEnum Yes = int32(0)

}

}

If you have lots of code in other assemblies that make use of this interface, your best bet is to keep it inside a separate VB.NET assembly, and reference it from your C# projects. Otherwise, it's safe to convert it, but you'll have to change any code that uses it to return the different type.

Jeremy Frey