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???
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.
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.
If you change visibility modifiers from a more restrictive modifier to a less restrictive modifier you allow class clients access to methods designated for internal use. Essentially you've provided a means to alter class state that may not be safe.
Reducing visibility is impossible because if Base.Member was visible and Derived.Member was not visible, that would break the whole “Derived is a Base” concept in OOP. However, increasing visibility is disallowed maybe because the language developers think that changing the visibility would be a mistake most of the time. However, you can always use the new keyword to hide base class members by introducing a member with the same name but a different behavior. This new member belongs to the derived type’s interface, so of course you can still access the base type’s interface by casting to that base type. Depending on how you write your subclass, your new member might effectively increase the visibility of the base class’s property—but remember that the base class’s property can still be accessed directly (e.g., a subclass of your subclass could cast this to Base and bypass your property).
The question here is how to both override and new the same named member (identifier) in a subclass. That is apparently not possible. At the very least, I can say through experimentation that public new override string foo(){return "";} is not a syntax for that. However, you can get the same effect by using two subclasses:
using System;
class Base
{
protected virtual string foo()
{
return "Base";
}
public void ExhibitSubclassDependentBehavior()
{
Console.WriteLine("Hi, I am {0} and {1}.", GetType(), foo());
}
}
abstract class AbstractDerived : Base
{
protected virtual string AbstractFoo()
{
return base.foo();
}
protected override string foo()
{
return AbstractFoo();
}
}
class Derived : AbstractDerived
{
protected override string AbstractFoo()
{
return "Deprived";
}
public new string foo()
{
return AbstractFoo();
}
}
static class Program
{
public static void Main(string[] args)
{
var b = new Base();
var d = new Derived();
Base derivedAsBase = d;
Console.Write(nameof(b) + " -> "); b.ExhibitSubclassDependentBehavior(); // "b -> Hi, I am Base and Base."
Console.WriteLine(nameof(d) + " -> " + d.foo()); // "d -> Deprived"
Console.Write(nameof(derivedAsBase) + " -> "); derivedAsBase.ExhibitSubclassDependentBehavior(); // "derivedAsBase -> Hi, I am Derived and Deprived."
}
}
The intermediate subclass (AbstractDerived) uses override and introduces a new, differently-named member that the subclass and sub-subclasses can continue to override the base class’s member as they see fit. The sub-subclass (Derived) uses new to introduce the new API. Since you can only use new or override with a particular identifier only once per level of subclassing, you need two levels of subclassing to effectively use both on the same identifier.
So, in a way, you can change the visibility while overriding methods—it’s just a pain and there’s no syntax I know of to accomplish it with just one level of inheritance. However, you might have to use some trick like this depending on what interfaces you’re trying to implement and what your base class looks like. I.e., this may or may not be what you actually want to do. But I still wonder why C# does not just support this to begin with. IOW, this “answer” is just a re-expression of the OP’s question with a workaround ;-).
You can make derived class's access less than the base's, but not more. Otherwise it would contradict base's definition and expose its components beyond what was intended.
Reasons are obvious. Security and Integrity of the objects.
In this particular example, what if external entities start modifying the property of the object which is protected according the base-class. Things will go haywire. What about the client-code that is written against the base-class to which all/any derived class must conform to.
if it had different access modifiers you can't really consider it the same method any more. kind of suggests a problem with the design of the model.
a better question would be why would you want to change the access modifiers?
Overriding is a term which enables you to change or augment the behavior of methods in a base class. Overriding gives you the control to write new logic for an existing method.
Changing the method signature of a base class is somewhat like writing a new method instead of overriding the existing one. It contradicts the purpose of overriding a method. So maybe the reason why you cannot change the access modifier while overriding methods in C#.
Related
In C# what does the term shadowing mean? I have read this link but didn't fully understand it.
Shadowing hides a method in a base class. Using the example in the question you linked:
class A
{
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A
{
public new int Foo() { return 1;}
public override int Bar() {return 1;}
}
Class B overrides the virtual method Bar. It hides (shadows) the non-virtual method Foo. Override uses the override keyword. Shadowing is done with the new keyword.
In the code above, if you didn't use the new keyword when defining the Foo method in class B, you would get this compiler warning:
'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
Overriding : redefining an existing method on a base class
Shadowing : creating an entirely new method with the same signature as one in a base class
Suppose I have a base class that implements a virtual method:
public class A
{
public virtual void M() { Console.WriteLine("In A.M()."); }
}
I also have a derived class that also defines a method M:
public class B : A
{
// could be either "new" or "override", "new" is default
public void M() { Console.WriteLine("In B.M()."); }
}
Now, suppose I write a program like this:
A alpha = new B(); // it's really a B but I cast it to an A
alpha.M();
I have two different choices for how I want that to be implemented. The default behavior is to call A's version of M. (This is identical to the behavior if you applied the "new" keyword to B.M().)
This is called "shadowing" when we have a method with the same name but a different behavior when called from the base class.
Alternately, we could have specified "override" on B.M(). In this case, alpha.M() would have called B's version of M.
Shadowing consist on hiding a base class method with a new definition in a child class.
The difference between hiding and overriding has to do with the way methods are invoked.
That way, when a virtual method is overridden, the call address for the method call table of the base class is replaced with the address of the child routine.
On the other hand, when a method is hidden, a new address is added to the method call table of the child class.
When a call is made to the method in question:
The method call table class type is obtained, if we are invoking with a reference to the base class then the base class method table is obtained, if we have a reference to the child class, then the child class method table is obtained.
The method is searched in the table, if it's found then the invocation takes place, otherwise the base class method table is searched.
If we invoke the method with a reference to the child class then the behavior is the same, if the method has been overridden, the method address will be found in the base class, if the method was hidden the method address will be found on the child class, and since it has been already found, base class table will not be searched.
If we invoke the method with a reference to the base class then behavior changes. When overriding, as the method address overwrites base class entry, we will call the child method, even when holding a reference to the base class. With shadowing, the base class method table (which is the only one visible as we hold a reference to the base class) contains the virtual method address, and therefore, the base class method will be called.
In general shadowing is a bad idea, as it introduces a difference on the behavior of an instance depending on the reference we have to it.
Expanding on Kent's correct answer
When disambiguating when which method will be called, I like to think of shadowing vs. overriding with the following
Shadowing: The method called depends on the type of the reference at the point the call is made
Overriding: The method called depends on the type of the object at the point the call is made.
Here's an MSDN article on Shadowing. The language examples are in Visual Basic (unfortunately there is no equivalent C# page on MSDN), but it deals generally with the concepts and hopefully should help you understand anyway.
Edit: Seems like there is a C# article on shadowing, except that it's called hiding in C#. Also, this page offers a good overview.
If you want to hide Base class method , Use override in base [virtual method in base]
if you want to hide Child class method , Use new in base [nonvirtual method in base]->shadow
Base B=new Child()
B.VirtualMethod() -> Calls Child class method
B.NonVirtualMethod() -> Calls Base class method
Overriding: same name and exactly the same parameters, implemented
differently in sub classes.
If treated as DerivedClass or BaseClass, it used derived method.
Shadowing: same name and exactly the same parameters, implemented differently in sub classes.
If treated as DerivedClass, it used derived method.
if treated as BaseClass, it uses base method.
Hope this brief explanation helps.
Shadowing - Replaces the complete element of the parent class
class InventoryAndSales
{
public int InvoiceNumber { get; set; }
}
//if someone calls for this class then the InvoiceNumber type is now object
class NewInventoryAndSales : InventoryAndSales
{
public new object InvoiceNumber { get; set; }
}
Overriding - Only replaces the implementation. It doesn't replace the data type it doesn't replace like for example you have a variable it doesn't convert it into a method so if there is a method it will use that method and only changed the implementation
class InventoryAndSales
{
public virtual int GetTotalSales(int a, int b)
{
return a + b;
}
}
class NewInventoryAndSales : InventoryAndSales
{
//it replaces the implementation in parent class
public override int GetTotalSales(int a, int b)
{
return a * b;
}
}
Shadowing isn't something I'd be worried about understanding or implementing unless it "fits" the problem really well. I've seen it used improperly and cause weird logic bugs much more often than being used correctly. The big cause, I think, is when the programmer forgets to put overrides in a method signature then the compiler warning will suggest the new keyword. I've always felt that it should recommend using override instead.
private static int x = 10;
static void Main(string[] args)
{ int x = 20;
if (Program.x == 10)
{
Console.WriteLine(Program.x);
}
Console.WriteLine(x);}
Output:
10
20
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???
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.
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.
If you change visibility modifiers from a more restrictive modifier to a less restrictive modifier you allow class clients access to methods designated for internal use. Essentially you've provided a means to alter class state that may not be safe.
Reducing visibility is impossible because if Base.Member was visible and Derived.Member was not visible, that would break the whole “Derived is a Base” concept in OOP. However, increasing visibility is disallowed maybe because the language developers think that changing the visibility would be a mistake most of the time. However, you can always use the new keyword to hide base class members by introducing a member with the same name but a different behavior. This new member belongs to the derived type’s interface, so of course you can still access the base type’s interface by casting to that base type. Depending on how you write your subclass, your new member might effectively increase the visibility of the base class’s property—but remember that the base class’s property can still be accessed directly (e.g., a subclass of your subclass could cast this to Base and bypass your property).
The question here is how to both override and new the same named member (identifier) in a subclass. That is apparently not possible. At the very least, I can say through experimentation that public new override string foo(){return "";} is not a syntax for that. However, you can get the same effect by using two subclasses:
using System;
class Base
{
protected virtual string foo()
{
return "Base";
}
public void ExhibitSubclassDependentBehavior()
{
Console.WriteLine("Hi, I am {0} and {1}.", GetType(), foo());
}
}
abstract class AbstractDerived : Base
{
protected virtual string AbstractFoo()
{
return base.foo();
}
protected override string foo()
{
return AbstractFoo();
}
}
class Derived : AbstractDerived
{
protected override string AbstractFoo()
{
return "Deprived";
}
public new string foo()
{
return AbstractFoo();
}
}
static class Program
{
public static void Main(string[] args)
{
var b = new Base();
var d = new Derived();
Base derivedAsBase = d;
Console.Write(nameof(b) + " -> "); b.ExhibitSubclassDependentBehavior(); // "b -> Hi, I am Base and Base."
Console.WriteLine(nameof(d) + " -> " + d.foo()); // "d -> Deprived"
Console.Write(nameof(derivedAsBase) + " -> "); derivedAsBase.ExhibitSubclassDependentBehavior(); // "derivedAsBase -> Hi, I am Derived and Deprived."
}
}
The intermediate subclass (AbstractDerived) uses override and introduces a new, differently-named member that the subclass and sub-subclasses can continue to override the base class’s member as they see fit. The sub-subclass (Derived) uses new to introduce the new API. Since you can only use new or override with a particular identifier only once per level of subclassing, you need two levels of subclassing to effectively use both on the same identifier.
So, in a way, you can change the visibility while overriding methods—it’s just a pain and there’s no syntax I know of to accomplish it with just one level of inheritance. However, you might have to use some trick like this depending on what interfaces you’re trying to implement and what your base class looks like. I.e., this may or may not be what you actually want to do. But I still wonder why C# does not just support this to begin with. IOW, this “answer” is just a re-expression of the OP’s question with a workaround ;-).
You can make derived class's access less than the base's, but not more. Otherwise it would contradict base's definition and expose its components beyond what was intended.
Reasons are obvious. Security and Integrity of the objects.
In this particular example, what if external entities start modifying the property of the object which is protected according the base-class. Things will go haywire. What about the client-code that is written against the base-class to which all/any derived class must conform to.
if it had different access modifiers you can't really consider it the same method any more. kind of suggests a problem with the design of the model.
a better question would be why would you want to change the access modifiers?
Overriding is a term which enables you to change or augment the behavior of methods in a base class. Overriding gives you the control to write new logic for an existing method.
Changing the method signature of a base class is somewhat like writing a new method instead of overriding the existing one. It contradicts the purpose of overriding a method. So maybe the reason why you cannot change the access modifier while overriding methods in C#.
I have just learned how to mask a base class member (using new) but am missing the point as to why I would want to do that. Does masking provide us with a certain level of protection as is the case in using encapsulation? Please advise.
You will very rarely use "new" to mask a base class member.
It's mainly used for the cases where the derived class had the member first, and then it was added to the base class --- the same name for a different purpose. The new is there to that you acknowledge that you know you are using it differently. When a base member is added in C++, it just silently merges the existing method into the inheritance chain. In C#, you will have to choose between new and override, to show you know what is happening.
It's not just used for masking. It actually breaks the inheritance chain, so if you call the base class method, the method in the derived class will not be called (just the one in the base class).
You're essentially creating a new method that has nothing to do with the base class method. Hence the "new" keyword.
Keeping that in mind the "new" keyword can be used if you want to define a method with the same signature as a base type method, but having a different return type.
The only valid safe examples that I've come across is being more specific with return types or providing a set accessor on a property. I'm not saying those are the only ones, but that's all I've found.
For example, suppose you have a very simple base that looks like this:
public abstract class Base
{
public string Name { get; protected set; }
public Base(string name)
{ Name = name; }
}
You could have a derived that looks more like this:
public class Derived : Base
{
public new string Name
{
get { return base.Name; }
set { base.Name = value; }
}
public Derived(string name) : base(name)
{ }
}
Assuming business rules allows this one specific Derived to have a changeable name, I believe this is acceptable. The problem with new is that it changes behavior depending on what type the instance is viewed as. For example, if I were to say:
Derived d = new Derived("Foo");
d.Name = "Bar";
Base b = d;
b.Name = "Baz"; // <-- No set available.
In this trivial example, we're fine. We are overriding the behavior with new, but not in a breaking way. Changing return types requires a bit more finesse. Namely, if you use new to change a return type on a derived type, you shouldn't allow that type to be set by the base. Check out this example:
public class Base
{
public Base(Base child)
{ Child = child; }
public Base Child { get; private set; }
}
public class Derived
{
public Derived(Derived child) : base(child)
{ }
public new Derived Child
{ get { return (Derived)base.Child; } }
}
If I could set Child on the Base class, I could have a casting problem in the Derived class. Another example:
Derived d = new Derived(someDerivedInstance);
Base b = d;
var c = b.Child; // c is of type Base
var e = d.Child; // e is of type Derived
I can't break any business rules by treating all of my Derived classes as Bases, it's just convenient to not type check and cast.
I have just learned how to mask a base class member (using new)
FYI this feature is usually called "hiding" rather than "masking". I think of "masking" as clearing bits in a bit array.
am missing the point as to why I would want to do that.
Normally you don't want to. For some reasons to use and not use this feature, see my article on the subject from 2008:
http://blogs.msdn.com/b/ericlippert/archive/2008/05/21/method-hiding-apologia.aspx
Does masking provide us with a certain level of protection as is the case in using encapsulation?
No, it does not.
What you are referring to is called Name Hiding. It is mostly a convenience feature. If you are inheriting from a class for which you do not control the source using new will let you change the behavior of a method even if it wasn't declared as virtual (or completely change the signature if it is virtual). The new keyword simply suppresses a compiler warning. You are basically informing the compiler that you are intentionally hiding the method from a parent class.
Delphi had the reintroduce keyword for the same reason.
What does this buy you other than a suppressed warning? Not a whole lot. You can't access the new method from a parent class. You can access it from an interface if your child class directly implements the interface (as apposed to inheriting it from its parent class). You can still call the parent class' member from the child. Any additional descendants of your class will inherit the new member rather than the one in the parent.
This is actually called member hiding. There are a couple of common scenarios where this can be appropriately used.
It allows you to work around versioning issues in which either the base or derived class author unwittingly creates a member name that collides with an existing identifier.
It can be used to simulate covariance on return types.
Regarding the first point...it is possible that an author of a base class could later add a member with the same name as an exisiting member in a derived class. The base class author may not have an knowledge of the derived classes and thus there is no expectation that she should avoid name collisions. C# supports the independent evolution of class hierarchies using the hiding mechanisms.
Regarding the second point...you may want a class to implement an interface that dictates a certain method signature and so you are locked into returning instances of a certain type only while at the same time you have subclassed that type and would really like for callers to see the concrete type instead. Consider this example.
public interface IFoo { }
public class ConcreteFoo { }
public abstract class Base
{
private IFoo m_Foo;
public Base(IFoo x) { m_Foo = x; }
public IFoo Foo { get { return m_Foo; } }
}
public class Derived
{
public Derived(ConcreteFoo x) : base(x) { }
public new ConcreteFoo Foo { get { return (ConcreteFoo)base.Foo; } }
}
In the following code:
public abstract class MyClass
{
public abstract bool MyMethod(
Database database,
AssetDetails asset,
ref string errorMessage);
}
public sealed class MySubClass : MyClass
{
public override bool MyMethod(
Database database,
AssetDetails asset,
ref string errorMessage)
{
return MyMethod(database, asset, ref errorMessage);
}
public bool MyMethod(
Database database,
AssetBase asset,
ref string errorMessage)
{
// work is done here
}
}
where AssetDetails is a subclass of AssetBase.
Why does the first MyMethod call the second at runtime when passed an AssetDetails, rather than getting stuck in an infinite loop of recursion?
C# will resolve your call to your other implementation because calls to a method on an object, where the class for that object has its own implementation will be favored over an overridden or inherited one.
This can lead to subtle and hard-to-find problems, like you've shown here.
For instance, try this code (first read it, then compile and execute it), see if it does what you expect it to do.
using System;
namespace ConsoleApplication9
{
public class Base
{
public virtual void Test(String s)
{
Console.Out.WriteLine("Base.Test(String=" + s + ")");
}
}
public class Descendant : Base
{
public override void Test(String s)
{
Console.Out.WriteLine("Descendant.Test(String=" + s + ")");
}
public void Test(Object s)
{
Console.Out.WriteLine("Descendant.Test(Object=" + s + ")");
}
}
class Program
{
static void Main(string[] args)
{
Descendant d = new Descendant();
d.Test("Test");
Console.In.ReadLine();
}
}
}
Note that if you declare the type of the variable to be of type Base instead of Descendant, the call will go to the other method, try changing this line:
Descendant d = new Descendant();
to this, and re-run:
Base d = new Descendant();
So, how would you actually manage to call Descendant.Test(String) then?
My first attempt looks like this:
public void Test(Object s)
{
Console.Out.WriteLine("Descendant.Test(Object=" + s + ")");
Test((String)s);
}
This did me no good, and instead just called Test(Object) again and again for an eventual stack overflow.
But, the following works. Since, when we declare the d variable to be of the Base type, we end up calling the right virtual method, we can resort to that trickery as well:
public void Test(Object s)
{
Console.Out.WriteLine("Descendant.Test(Object=" + s + ")");
Base b = this;
b.Test((String)s);
}
This will print out:
Descendant.Test(Object=Test)
Descendant.Test(String=Test)
you can also do that from the outside:
Descendant d = new Descendant();
d.Test("Test");
Base b = d;
b.Test("Test");
Console.In.ReadLine();
will print out the same.
But first you need to be aware of the problem, which is another thing completely.
See the section of the C# Language Specification on Member Lookup and Overload Resolution. The override method of the derived class is not a candidate because of the rules on Member Lookup and the base class method is not the best match based on the Overload Resolution rules.
Section 7.3
First, the set of all accessible (Section 3.5) members named N declared in T and the base types (Section 7.3.1) of T is constructed. Declarations that include an override modifier are excluded from the set. If no members named N exist and are accessible, then the lookup produces no match, and the following steps are not evaluated.
Section 7.4.2:
Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way, as described in detail in the sections listed above. For example, the set of candidates for a method invocation does not include methods marked override (Section 7.3), and methods in a base class are not candidates if any method in a derived class is applicable (Section 7.5.5.1). (emphasis mine)
As others have correctly noted, when given the choice between two applicable candidate methods in a class, the compiler always chooses the one that was originally declared "closer" to the class which contains the call site when examining the base class hierarchy.
This seems counterintuitive. Surely if there is an exact match declared on a base class then this is a better match than an inexact match declared on a derived class, yes?
No. There are two reasons to choose the more derived method always over the less derived method.
The first is that the author of the derived class has much more information than the author of the base class. The author of the derived class knows everything about both the base class and the derived class, which is, after all, the class that the caller is actually using. When given the choice between calling a method written by someone who knows everything vs someone who knows only something about the type the caller is using, clearly it makes sense to prioritize calling the method written by the designer of the derived class.
Second, making that choice leads to a form of the Brittle Base Class Failure. We wish to protect you from this failure, and therefore have written the overload resolution rules so as to avoid it whenever possible.
For a detailed explanation of how this rule protects you from the Brittle Base Class Failure, see my article on the subject.
And for articles on other ways that languages deal with Brittle Base Class situations, click here.
Because that's the way the language is defined. For virtual members, the Implementation which is called at runtime, when a method exists in both a base class and a derived class, is based on the concrete type of the object which the method is called against, not the declared type of the variable which holds the reference to the object. Your first MyMethod is in an abstract class. So it can never be called from an object of type MyClass - because no such object can ever exist. All you can instanitate is derived class MySubClass. The concrete type is MySubClass, so that implementation is called, no matter that the code that calls it is in the base class.
For non-virtual members/methods, just the opposite is true.
I'm moving from PHP to C#.
In PHP it was simple and straightforward to use abstract classes to create a "cascading override" pattern, basically "the base class method will take care of it unless the inheriting class has a method with the same signature".
In C#, however, I just spent about 20 minutes trying out various combinations of the keywords new, virtual, abstract, and override in the base and inheriting classes until I finally got the right combination which does this simple cascading override pattern.
So even those the code below works the way I want it, these added keywords suggest to me that C# can do much more with abstract classes. I've looked up examples of these keywords and understand basically what they do, but still can't imagine a real scenario in which I would use them other than this simple "cascading override" pattern. What are some real world ways that you implement these keywords in your day-to-day programming?
code that works:
using System;
namespace TestOverride23433
{
public class Program
{
static void Main(string[] args)
{
string[] dataTypeIdCodes = { "line", "wn" };
for (int index = 0; index < dataTypeIdCodes.Length; index++)
{
DataType dataType = DataType.Create(dataTypeIdCodes[index]);
Console.WriteLine(dataType.GetBuildItemBlock());
}
Console.ReadLine();
}
}
public abstract class DataType
{
public static DataType Create(string dataTypeIdCode)
{
switch (dataTypeIdCode)
{
case "line":
return new DataTypeLine();
case "wn":
return new DataTypeWholeNumber();
default:
return null;
}
}
//must be defined as virtual
public virtual string GetBuildItemBlock()
{
return "GetBuildItemBlock executed in the default datatype class";
}
}
public class DataTypeLine : DataType
{
public DataTypeLine()
{
Console.WriteLine("DataTypeLine just created.");
}
}
public class DataTypeWholeNumber : DataType
{
public DataTypeWholeNumber()
{
Console.WriteLine("DataTypeWholeNumber just created.");
}
//new public override string GetBuildItemBlock() //base method is erroneously executed
//public override string GetBuildItemBlock() //gets error "cannot override inherited member because it is not marked virtual, abstract, or override"
public override string GetBuildItemBlock()
{
return "GetBuildItemBlock executed in the WHOLENUMBER class.";
}
}
}
virtual/override is the core polymorphism pair; sounds like you've already cracked these
abstract is like virtual, but there is no sensible base implementation; use-cases: perhaps a Stream, where it is necessary for the actual implementation to do something with the bytes. This forces the class to be abstract
new should usually be avoided; it breaks polymorphism... the most common case is to re-expose with a more specific signature / return-type (perhaps in a sealed class, since it doesn't get prettier up the chain...) - see SqlConnection.CreateCommand (vs DbConnection.CreateCommand), or (perhaps more notably) IEnumerator<T>.Current (vs IEnumerator.Current)
It appears you have already figured out virtual and override from your example, so:
'abstract' can also be applied on members instead of 'virtual', in which case you do not specify an implementation for the method (';' directly after the signature). This forces all concrete descendants to implement the method.
'new' has nothing to do with inheritance, but can instead be used in a descendant class on a member to hide a member in the base class that has the exact same signature.
In a nutshell ;)
Further to the other answers.
Overrride for when you wish to allow child classes to perform their own processing, no processing or even just call the parent class processing for a function. An override or virtual function does not have to be implemented in descendent classes.
Abstract when you don't wish to perform any processing in your base class but want that method to be implemented by any inheriting class. (Best when the inheriting class behaviour can differ drastically). If a class contains nothing but abstract methods then it is effectively an interface type. A function specified as abstract MUST be implemented in the child class (the compiler will throw an error if not).