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.
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#.
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#.
Here's the situation. I have a base class which implements a method that accepts a string, and sets a property to the value of that string. Under that, I have a group of concrete classes that implement the base. Some of the concrete classes can accept any string value to be stored. However, some of the class's values are constrained within an Enumerated series of values. The final value is still a string, but the value must be within that enumerated set of possible values.
Here's what I'd like to do: For the classes which use an enum-restricted value, I want to implement an overload to the string method that calls the string method with the correct value. However, I also want to lock the string implementation out so that only the enum implementation can be used to pass a new value in, in order to enforce the enum restriction.
I know at this point that this just isn't going to happen through the use of override or new in the method declaration. I also know that I could create a hierarchy like Base -> [BaseString|BaseEnum] -> Concrete and use sealing to keep the concrete implementation from allowing the string-based implementation to be used. What I'd like to know is if there's another way to do this that skips the extra level of hierarchy and allows me to just say "If method overload is present in concrete class, lock method."
public class Abstract {
public virtual string ValueHolder { get; private/protected set; }
public virtual void DoSomething( string s ) { ...; }
}
public class ConcreteEnum : Abstract {
public void DoSomething( Enum e ) {
base.DoSomething( "String somehow extracted from enum");
}
}
public class ConcreteString : Abstract { ... }
public class Main {
ConcreteString sc = new ConcreteString();
ConcreteEnum se = new ConcreteEnum();
sc.DoSomething( "I don't have an overload defined,
so I'm using my base's string handler method.
I can be any value, I have no restrictions." );
se.DoSomething( SomeEnum.MyValueWillBeRunThroughTheBaseStringHandler );
se.DoSomething( "I don't work because there's an
overload defined in my concrete class, and my
value is restricted to a specific set of
possibilities." );
}
As I said, I know that there are other viable ways of doing this, I just want to know if this is possible/more clean than those alternatives.
You would basically need to just validate the string in the derived class:
public class ConcreteEnum : Abstract {
public void DoSomething( Enum e ) {
base.DoSomething( "String somehow extracted from enum");
}
public override void DoSomething( string s ) {
// Validate s, then do something with it
}
}
You can't remove the method entirely, since it is a member of the superclass and hence part of the class interface. For example, if you passed an instance of ConcreteEnum to a method that takes an Abstract object and expected the DoSomething(string) method to work, but it was magically gone, all hell would break loose.
But you always have the option of overriding the behavior in a subclass to throw exceptions when an invalid value is supplied. You could even override it to just throw a NotSupportedException.
EDIT: If the base class DoSomething method is not supposed to be consumed except in subclasses (not saying it is, but you didn't really specify either way), why not just make it protected?
I have this code snippet and I would like to know why is the output as written in comment below:
interface I {
void m1();
void m2();
void m3();
}
class A : I {
public void m1() { Console.WriteLine("A.m1()"); }
public virtual void m2() { Console.WriteLine("A.m2()"); }
public virtual void m3() { Console.WriteLine("A.m3()"); }
}
class C : A, I {
public new void m1() { Console.WriteLine("C.m1()"); }
public override void m2() { Console.WriteLine("C.m2()"); }
public new void m3() { Console.WriteLine("C.m3()"); }
}
------
C c = new C();
((I) ((A) c)).m1(); //"C.m1()"
((I) ((A) c)).m2(); //"C.m2()"
((I) ((A) c)).m3(); //"C.m3()"
One original guess of what the output shoud be was:
A.m1();
C.m2();
A.m3();
Change class C to this:
class C : A {
public new void m1() { Console.WriteLine("C.m1()"); }
public override void m2() { Console.WriteLine("C.m2()"); }
public new void m3() { Console.WriteLine("C.m3()"); }
}
Explanation from Jeffrey Richter:
The C# compiler requires that a method that implements an interface be marked as public. The
CLR requires that interface methods be marked as virtual. If you do not explicitly mark
the method as virtual in your source code, the compiler marks the method as virtual and
sealed; this prevents a derived class from overriding the interface method. If you explicitly
mark the method as virtual, the compiler marks the method as virtual (and leaves it
unsealed); this allows a derived class to override the interface method.
If an interface method is sealed, a derived class cannot override the method. However, a
derived class can re-inherit the same interface and can provide its own implementation for the
interface's methods. When calling an interface's method on an object, the implementation
associated with the object's type is called.
Because C class also implements I interface, than when we calling interface methods on C object, we will call implementation accosicated with the object's type is called (i.e class C methods) but not methods derived from C's base class (not A class methods).
All these type-casts are redundant and I'm pretty sure they get optimized away by the compiler.
Here's what I mean. (A) c is redundant since C is A, so we're left just with (I)c, which is redundant as well, since C implements I. Thus, we have just an instance of C class, for which the compiler applies normal resolution rules.
EDIT
Turns out, I was completely wrong. This document describes what happens:
Interface mapping for a class or struct C locates an implementation for each member of each interface specified in the base class list of C. The implementation of a particular interface member I.M, where I is the interface in which the member M is declared, is determined by examining each class or struct S, starting with C and repeating for each successive base class of C, until a match is located:
If S contains a declaration of an explicit interface member implementation that matches I and M, then this member is the implementation of I.M.
Otherwise, if S contains a declaration of a non-static public member that matches M, then this member is the implementation of I.M.
I think you're misunderstanding what the cast operator does for reference conversions.
Suppose you have a reference to an instance of C on the stack. That's a certain set of bits. You cast the thing on the stack to A. Do the bits change? No. Nothing changes. It's the same reference to the same object. Now you cast it to I. Do the bits change this time? No. Same bits. Same reference. Same object.
An implicit reference conversion via a cast like this simply tells the compiler to use different rules when figuring out at compile time what method to call.
So the casts to "A" are completely irrelevant and ignored by the compiler. All the compiler knows or cares about is that you have an expression of type I, and you're calling a method on it. The compiler generates a call that says "at runtime, look at the object reference that is on the stack and invoke whatever is in the "I.m1" slot of the object.
The way to figure this stuff out is to think about the slots. Every interface and class defines a certain number of "slots". At runtime, every instance of a class has those slots filled in with references to methods. The compiler generates code that says "invoke whatever is in slot 3 of that object", and that's what the runtime does -- looks in the slot, calls what's there.
In your example there are all kinds of slots. The interface requires three slots, the base class provides more, and the "new" methods of the derived class provide two more. When an instance of the derived class is constructed, all of those slots are filled in, and, understandably, the slots associated with I are filled in with the matching members of the derived class.
Does that make sense?
Casting does not matter as C already contains A and I.
for ((I) ((A) c)).m1() and ((I) ((A) c)).m3(): - The "new" keyword hides the A.m1 implementation (in fact without the new keyword you will get a warning). So C.M1 and C.M3 are chosen.
For ((I) ((A) c)).m2():
- The override takes care that the C.M2 implementation is chosen.