views:

90

answers:

5

I can't do this

interface InterfaceA
{
    void MethodA();
}

class ClassA : InterfaceA
{
    virtual void InterfaceA.MethodA()
    // Error: The modifier 'virtual' is not valid for this item
    {
    }
}

Where the following works

class ClassA : InterfaceA
{
    public virtual void MethodA()
    {
    }
}

Why? How to circumvent this?

+1  A: 

You cannot use the virtual modifier with the static, abstract, private or override modifiers. default modifier is private

lukas
Interestingly for explicit implementations the modifier is public, though it can only be accessed if the instance is cast to the respective interface type.
Jader Dias
+1  A: 

I think this is because when a member is explicitly implemented, it cannot be accessed through a class instance, but only through an instance of the interface.

So making something 'virtual' really does not make sense in this case, since virtual means that you intend to override it in an inherited class. Implementing an interface explicitly and making it virtual would be contradictory. Which also may be why the compiler disallows this.

To work around it I think csharptest.net's or Philip's answer sounds like it would do the trick

Roberto Sebestyen
+2  A: 

According to C# language spec:

It is a compile-time error for an explicit interface member implementation to include access modifiers, and it is a compile-time error to include the modifiers abstract, virtual, override, or static.

You can "get around" it only by calling your virtual method from the explicit interface implementation.

Philip Rieck
+1  A: 

You have to do something like this:

interface InterfaceA
{
    void MethodA();
}

class ClassA : InterfaceA
{
    void InterfaceA.MethodA()
    { MethodB(); }

    protected virtual void MethodB()
    { 
    }
}

Often this is a superior approach anyway as the internal method may change signature without changing the interface. Take a more real-word example:

interface IOrderDetails
{
    void PlaceOrder();
}

//Sometime later you extend with:
interface IOrderDetails2 : IOrderDetails
{
    void PlaceOrder(IUser user);
}

//Implementation
class Order : IOrderDetails, IOrderDetails2
{
    static readonly IUser AnonUser;

    void IOrderDetails.PlaceOrder()
    { OnPlaceOrder(AnonUser); }
    void IOrderDetails2.PlaceOrder(IUser user)
    { OnPlaceOrder(user); }

    protected virtual void OnPlaceOrder(IUser user)
    { 
    }
}

Here you can see as the IOrderDetails2 was added we can safely refactor the existing virtual method (thus generating compile-time errors for derivations). Additionally this often allows you to provide common functionality, logging, and exception handling in the base implementation class...

csharptest.net