What are the rules for multiple casts in C#? - c#

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.

Related

Can we use two methods with same name and parameters in both parent class and the child class? [duplicate]

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

Will CLR check the whole inheritance chain to determine which virtual method to call?

The inheritance chain is as follows:
class A
{
public virtual void Foo()
{
Console.WriteLine("A's method");
}
}
class B:A
{
public override void Foo()
{
Console.WriteLine("B's method");
}
}
class C:B
{
public new virtual void Foo()
{
Console.WriteLine("C's method");
}
}
class D:C
{
public override void Foo()
{
Console.WriteLine("D's method");
}
}
then:
class Program
{
static void Main(string[] args)
{
A tan = new D();
tan.Foo();
Console.Read();
}
}
The result is, the method foo() in class B is called.
But in the reference:
When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member.
In my logic, CLR first finds Foo() is a virtual method, it looks into the method table of D, the runtime type, then it finds out there is an overriding member in this most derived class, it should call it and never realizes there is a new Foo() in the inheritance chain.
What's wrong with my logic?
Amy's answer is correct. Here's how I like to look at this question.
A virtual method is a slot that can contain a method.
When asked to do overload resolution, the compiler determines which slot to use at compile time. But the runtime determines what method is actually in that slot.
Now with that in mind let's look at your example.
A has one slot for Foo.
B has one slot for Foo, inherited
from A.
C has two slots for Foo. One inherited from B, and
one new. You said you wanted a new slot named Foo, so you got it.
D has two slots for Foo, inherited from C.
That's the slots. So, what goes in those slots?
In an A, A.Foo goes in the slot.
In a B, B.Foo goes in the slot.
In a C, B.Foo goes in the first slot and C.Foo goes in the second slot. Remember, these slots are completely different. You said you wanted two slots with the same name, so that's what you got. If that's confusing, that's your problem. Don't do that if it hurts when you do it.
In a D, B.Foo goes in the first slot and D.Foo goes in the second slot.
So now what happens with your call?
The compiler reasons that you are calling Foo on something of compile time type A, so it finds the first (and only) Foo slot on A.
At runtime, the contents of that slot is B.Foo.
So that's what's called.
Make sense now?
When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member.
You're starting from the wrong place. Your variable is of type A and contains an instance of D, so the virtual table used is A's 1. Following the text above, we check for an overriding member. We find one in B. C does not count because it is not overriding, it is shadowing the base method. And since D overrides C, not A or B, it doesn't count either. We're looking for the overriding member in the most derived class.
So the method found is B.Foo().
If you change C so it overrides instead of shadows, the found method will then be D, because it is the most derived overriding member.
If you instead change your object to an instance of B or C, B.Foo() will still be the chosen override. To clarify, this is what I mean:
A tan = new B();
tan.Foo(); // which foo is called? Why, the best Foo of course! B!
The reason B is called is because the inheritance chain we are searching spans from A (the variable type) to B (the runtime type). C and D are no longer part of that chain, and are not part of the virtual table.
If we instead change the code to this:
C tan = new D();
tan.Foo(); // which foo, which foo?
The inheritance chain we search spans from C to D. D is has an overriding member, so it's Foo is called.
Suppose you add another class Q that inherits from A, and R that inherits from Q, and so forth. You have two branches of inheritance, right? Which is chosen when searching for most derived type? Follow the path from A (your variable type) to D (the runtime type).
I hope this makes sense.
1 Not literally. The virtual table belongs to D because it is the runtime type and contains everything in its chain of inheritance, but its useful and easier to think of A as the starting point. You are searching for derived types, after all.

Why can't I call a public method in the subclass from the superclass when the object is of the subclass type?

I have a class B that is a subclass of class A. I create an object of type B and call OnlyA() on it, but inside OnlyA() the call to OnlyB() causes a compiler error.
From my understanding, OnlyB() is the same as this.OnlyB() and the method called should be chosen from the object's class (B), not the current class where code is being executed (A). This is why the call to Both() calls the method in B, not A. So why is it searching for OnlyB() in A, not B? How am I supposed to know when the method called is chosen from the object's class or the current class?
class Program
{
static void Main(string[] args)
{
B bRefB = new B();
bRefB.OnlyA();
}
}
class A
{
public void OnlyA()
{
Console.WriteLine("In A - OnlyA()");
OnlyB(); // compiler error
Both(); // calls the method in B
}
public virtual void Both()
{
Console.WriteLine("In A - Both()");
}
}
class B : A
{
public void OnlyB()
{
Console.WriteLine("In B - OnlyB()");
}
public override void Both()
{
Console.WriteLine("In B - Both()");
}
}
You are absolutely correct that OnlyB is the same as this.OnlyB. And that's the issue; this is of type A. It has no knowledge that B even exists (nor should it).
Superclasses do not, and are not supposed to, have any knowledge about the fact that they have derived classes at all let alone what methods are in them. Its not an issue of "searching"; what happens when you have C that doesn't define OnlyB? What method would be called?
Subclasses on the other hand are always subclasses of the super class; and so it is safe for them to invoke base class methods.
Bradely's answer covers why your code does not work (this is of type A). Here is correct way to write your requirements as code.
You want to call method based on run-time type of an object. Since compile time of this is type of the current object you need to cast it in some way to derived type before calling. Possible options:
just cast - statically checked that B has OnlyB, cast exception at run-time:
((B)this).OnlyB();
use dynamic - no static type checking, exception at run time if actual class does not have OnlyB method irrespective if it is from B, C...
dynamic b = this;
b.OnlyB();
manual reflection call (same as dynamic).
generics - see Curiously Recurring Template Pattern and generics constraints (C#)

Force the use of interface instead of concrete implementation in declaration (.NET)

In C++, you can do the following:
class base_class
{
public:
virtual void do_something() = 0;
};
class derived_class : public base_class
{
private:
virtual void do_something()
{
std::cout << "do_something() called";
}
};
The derived_class overrides the method do_something() and makes it private. The effect is, that the only way to call this method is like this:
base_class *object = new derived_class();
object->do_something();
If you declare the object as of type derived_class, you can't call the method because it's private:
derived_class *object = new derived_class();
object->do_something();
// --> error C2248: '::derived_class::do_something' : cannot access private member declared in class '::derived_class'
I think this is quite nice, because if you create an abstract class that is used as an interface, you can make sure that nobody accidentally declares a field as the concrete type, but always uses the interface class.
Since in C# / .NET in general, you aren't allowed to narrow the access from public to private when overriding a method, is there a way to achieve a similar effect here?
If you explicitly implement an interface, this will at least encourage people to use the interface type in the declaration.
interface IMyInterface
{
void MyMethod();
}
class MyImplementation : IMyInterface
{
void IMyInterface.MyMethod()
{
}
}
One will only see MyMethod after casting the instance to IMyInterface. If the declaration uses the interface type, there is no casting needed in subsequent uses.
MSDN page on explicit interface implementation (thanks Luke, saves me a few seconds^^)
IMyInterface instance = new MyImplementation();
instance.MyMethod();
MyImplementation instance2 = new MyImplementation();
instance2.MyMethod(); // Won't compile with an explicit implementation
((IMyInterface)instance2).MyMethod();
You can do this in the .Net world too, using explicit interface implementation
As an example, BindingList<T> implements IBindingList, but you have to cast it to IBindingList to see the method.
You are able to decrease a method's availability by marking it as new.
The example from MSDN's CA2222: Do not decrease inherited member visibility:
using System;
namespace UsageLibrary
{
public class ABaseType
{
public void BasePublicMethod(int argument1) {}
}
public class ADerivedType:ABaseType
{
// Violates rule: DoNotDecreaseInheritedMemberVisibility.
// The compiler returns an error if this is overridden instead of new.
private new void BasePublicMethod(int argument1){}
}
}
This is really more interesting as an academic exercise; if your code is truly dependent on not being able to call BasePublicMethod on ADerivedType, that's a warning sign of a dubious design.
The problem with this strategy, should it be implemented, is that the method is not truly private. If you were to upcast a reference to base_class, then the method is now public. Since it's a virtual method, user code will execute derived_class::do_something() eventhough it's marked as private.

Why does this work? Method overloading + method overriding + polymorphism

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.

Categories

Resources