C# error CS1540

 Sep 12th, 2012 

 , , ,

There are many ways in which one could violate the rules of Object Oriented Programming in C#. Fortunately, the C# compiler is smart enough to prevent many of them, like the one in the example below. Can you  figure out why the compiler doesn’t allow the call in the last method?

abstract class BaseClass
{
    protected abstract void AMethod(BaseClass arg);
}
class Derived : BaseClass
{
    protected override void AMethod(BaseClass arg)
    {
        arg.AMethod();
    }
}

The compiler will issue the following error:

Cannot access protected member ‘ConsoleApplication1.BaseClass.AMethod(ConsoleApplication1.BaseClass)’ via a qualifier of type ‘ConsoleApplication1.BaseClass'; the qualifier must be of type ‘ConsoleApplication1.Derived’ (or derived from it)

It might not be obvious why this isn’t allowed. From the definition of the protected keyword in C#:

The protected keyword is a member access modifier. A protected member is accessible within its class and by derived class instances.

This means that class Derived is allowed to call only protected methods defined inside it or in one of its base classes. But wait? Isn’t that what it is trying to do – access a protected method in one of its base classes? Yes, that’s right. However, that method is abstract, which means that any class deriving from BaseClass can provide its own implementation. Look at the following snippet:

abstract class BaseClass
{
    protected abstract void AMethod(BaseClass arg);
}
class Derived : BaseClass
{
    protected override void AMethod(BaseClass arg)
    {
        arg.AMethod();
    }
}
class Derived2: BaseClass
{
    protected override void AMethod(BaseClass arg)
    {
    }
}

If the call would be allowed, one might pass an instance of Derived2 as argument to AMethod in Derived, thus allowing Derived to call protected methods in Derived2. This would violate the definition of the protected keyword because Derived is not derived from Derived2.

Note: The compiler triggers the error only when the method in the base class is abstract or virtual.