Back to Basics - C # Compiler Error

public class BaseClass { protected void BaseMethod() { } } public class DerivedClass : BaseClass { public void Test() { DerivedClass d1 = new DerivedClass(); d1.BaseMethod(); // No error here. BaseClass b1 = new DerivedClass(); b1.BaseMethod(); // I get compile-time error for this. Why ? } } 

In the above code (compiled on VS2005), I get the following compile time error -

Error 1: It is not possible to access the protected member "BaseClass.BaseMethod ()" through a classifier such as "BaseClass"; qualifier must be of type "DerivedClass" (or derived from it)

Can someone explain this behavior? Something is going wrong here!

+6
c # compiler-errors
source share
3 answers

Eric Lippert just wrote a blog on this topic .

The main point is to ensure that the class can β€œtrust” the protected method's caller. Classes that share a common base class, even if this common base defines a protected method, are essentially unfamiliar in this regard.

Eric's example is based on the idea of ​​a banking application. Instead of recreating his example, I simply spew it here:

 // Good.dll: public abstract class BankAccount { abstract protected void DoTransfer( BankAccount destinationAccount, User authorizedUser, decimal amount); } public abstract class SecureBankAccount : BankAccount { protected readonly int accountNumber; public SecureBankAccount(int accountNumber) { this.accountNumber = accountNumber; } public void Transfer( BankAccount destinationAccount, User authorizedUser, decimal amount) { if (!Authorized(user, accountNumber)) throw something; this.DoTransfer(destinationAccount, user, amount); } } public sealed class SwissBankAccount : SecureBankAccount { public SwissBankAccount(int accountNumber) : base(accountNumber) {} override protected void DoTransfer( BankAccount destinationAccount, User authorizedUser, decimal amount) { // Code to transfer money from a Swiss bank account here. // This code can assume that authorizedUser is authorized. // We are guaranteed this because SwissBankAccount is sealed, and // all callers must go through public version of Transfer from base // class SecureBankAccount. } } // Evil.exe: class HostileBankAccount : BankAccount { override protected void Transfer( BankAccount destinationAccount, User authorizedUser, decimal amount) { } public static void Main() { User drEvil = new User("Dr. Evil"); BankAccount yours = new SwissBankAccount(1234567); BankAccount mine = new SwissBankAccount(66666666); yours.DoTransfer(mine, drEvil, 1000000.00m); // compilation error // You don't have the right to access the protected member of // SwissBankAccount just because you are in a // type derived from BankAccount. } } 

While what you imagine seems futile if it were allowed, the kind of shenimans you see here would be possible. Right now, you know that a call to a protected method either comes from your type (which you control), or from a class that you directly inherit (which you know at the time of compilation). If it was open to anyone inherited from the type of declaration, then you will never be guaranteed to find out the types that your protected method might call.

While you initialize your BaseClass variable BaseClass instance of your own class, the compiler only sees that the variable is of type BaseClass , placing you outside the circle of trust. The compiler does not analyze all destination calls (or potential destination calls) to determine if it is β€œsafe”.

+15
source share

From the C # spec:

When a protected instance member accesses outside the program text the class in which it is declared, and when a protected internal instance accesses a member outside the program text of the program in which it is declared, access is required to pass through the instance the type of the derived class in which access takes place.

MSDN link here .

+2
source share

This is taken directly from MSDN: http://msdn.microsoft.com/en-us/library/bcd5672a%28VS.71%29.aspx

A protected member of a base class is available in a derived class only if access is through the type of the derived class. For example, consider the following code segment:

 class A { protected int x = 123; } class B : A { void F() { A a = new A(); B b = new B(); ax = 10; // Error bx = 10; // OK } } 
+1
source share

All Articles