Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't we change access modifier while overriding methods in C#?

In C#, we can not change access modifier while overriding a method from base class. e.g.

Class Base {    **protected** string foo()    {        return "Base";    } }  Class Derived : Base {    **public** override string foo()    {        return "Derived";    } } 

This is not valid in C#, It will give compile time error.

I want to know the reason, why it's not allowed. Is there any technical problem or can it lead to something which is not consistent in terms of access restriction???

like image 920
Rumit Parakhiya Avatar asked Jun 04 '11 13:06

Rumit Parakhiya


People also ask

Can we change access modifier while overriding?

Yes, an overridden method can have a different access modifier but it cannot lower the access scope. Methods declared public in a superclass also must be public in all subclasses. Methods declared protected in a superclass must either be protected or public in subclasses; they cannot be private.

Which modifier Cannot override?

Rule #8:Constructors cannot be overridden. Because constructors are not methods and a subclass' constructor cannot have same name as a superclass' one, so there's nothing relates between constructors and overriding.

Can we change access modifier overridden method in C#?

An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier. You cannot use the new , static , or virtual modifiers to modify an override method.

What are the possible access modifiers a protected method can have if it is overridden?

Access Modifiers Default – No keyword required. Private. Protected. Public.


2 Answers

Changing the access modifier of a method in a derived type is pointless that's why it's not allowed:

Case 1: Override with a more restrictive access

This case is obviously not allowed due to the following situation:

class Base {     public virtual void A() {} }  class Derived: Base {     protected override void A() } 

Now we could say:

List<Base> list; list.Add(new Derived()); list[0].A() //Runtime access exception 

Case 2: Overriding with a less restrictive access modifier

What is the point? Hide the method and you are done. Obviously if someone calls through the base type they will not have access to the new method defined in the derived type but that is consistent with how the author of the base type wanted things to be so you have no "right" to change that. If you want the specifics of the derived class call from the derived class, in which case the new method works perfectly fine.

EDIT: Expanding case 2

What I am trying to say in case 2, is that you already have the means to change accessibility of any method (virtual or not) if you want to change accessibility.

Consider the following code:

public class Base {     protected virtual string WhoAmI()     {         return "Base";     } }  public class Derived : Base {     public new virtual string WhoAmI()     {         return "Derived";     } }  public class AnotherDerived : Derived {     public override string WhoAmI()     {         return "AnotherDerived";     } } 

With the new keyword you have effectively created a new virtual method for your Derived class with the same name and signature. Take note that it is ALLOWED to declare a new method virtual, so any class deriving from Derived will be allowed to override it.

What is not allowed is to have someone do the following:

 Base newBaseObject = new Derived();  newBaseObject.WhoAmI() //WhoAmI is not accessible. 

But this fact has nothing to do with being able to override WhoAmI() or not. Whatever the case this situation can never be because Base does not declare a public WhoAmI().

So in a theoretical C# where Derived.WhoAmI() could override Base.WhoAmI() there is no practical benefits in doing so because you will never be able to call the virtual method from the base class anyways, so the new option already meets your requirements.

I hope this makes it clearer.

like image 161
InBetween Avatar answered Oct 07 '22 17:10

InBetween


OK, I found a small note from Eric Lippert in the Annotated C# reference:

An overridden virtual method is still considered to be a method of the class that introduced it. The overload resolution rules in some cases prefer members of more derived types ... overriding a method does not "move" where that method belongs in this hierarchy.

So this is an intentional rule to prevent the 'brittle base class' problem and provide better versioning, ie less problems when a base class changes.

But note that it has nothing to do with security, type-safety or object-state.

like image 39
Henk Holterman Avatar answered Oct 07 '22 17:10

Henk Holterman