C# polymorphism - upcasting - c#

I would like to ask you for an explanation of this example:
public class A : B
{
public override void Method()
{
Console.WriteLine("A");
}
}
public class B
{
public virtual void Method()
{
Console.WriteLine("B");
}
}
Equation:
void Main()
{
B b = (B)new A();
b.Method(); // result A
}
Why upcasting did not work in this case?

How microsoft docs say:
If you want your derived class to have a member with the same name as a member in a base class, you can use the new keyword to hide the base class member. The new keyword is put before the return type of a class member that is being replaced. The following code provides an example:

Related

How to call the base class method?

We have the following code:
public class A
{
protected virtual void Method()
{
Console.Write("A");
}
}
public class B : A
{
protected override void Method()
{
Console.Write("B");
}
}
public class C : B
{
public void Some()
{
//How to call Method() from class A?
}
}
How to call Method() from class A in Some() method from class C?
We will assume that A and B are classes from the library and we can not change them.
Solution: https://stackoverflow.com/a/438952/8081796
B overrides Method() and A its marked as virtual and protected, the only way to call it (in its current format) is if B calls it somehow
public class B : A
{
protected override void Method()
{
base.Method();
Console.Write("B");
}
}
Or derived from A directly
public class C : A
{
public void Some()
{
Method();
}
}
virtual (C# Reference) | Microsoft Docs
The virtual keyword is used to modify a method, property, indexer, or
event declaration and allow for it to be overridden in a derived
class. For example, this method can be overridden by any class that
inherits it:
Furthermore
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.
protected (C# Reference)
A protected member is accessible within its class and by derived class
instances.
If you really want Method of A to be called here (without changing implementation of A or B's Method), you have to make below changes.
Change access specifier of Method of B class to new from override.
override will override the base class method. Making it new won't do it.
Change access specifier of A and B class Methods to public instead of protected
protected members of A won't be accessible inside your C class.
With this changes, check out below code. You will see that Method from class A is getting called.
static void Main()
{
var c = new C();
c.Some();
Console.ReadKey();
}
public class A
{
public virtual void Method()
{
Console.Write("A");
}
}
public class B : A
{
public new void Method()
{
Console.Write("B");
}
}
public class C : B
{
public void Some()
{
//How to call Method() from class A?
((A)this).Method();
}
}
If you cannot make the changes described as above, then I'm afraid you can't call A's Method :O .
This is impossible, because
The implementation of a virtual member can be changed by an overriding
member in a derived class.
B change implementation of A, therefore C have only B implementation as base and have not implementation of A.
Solution: https://stackoverflow.com/a/438952/8081796

Is it possible to tell apart overridden and hidden method?

Consider these variants:
class A
{
public virtual void Doit()
{
}
}
class B : A
{
public new virtual void Doit()
{
}
}
or
class B : A
{
public override virtual void Doit()
{
}
}
I cannot find the difference in the returned results of the call typeof(B).GetMethod("Doit");
In both cases MethodInfo.DecalringType is class B and other properties seem the same.
Do I miss something or there is no way to distinguish them?
Update:
When I ran the sample in LINQPAd I noticed slight difference in Attributes property:
for new virtual value was - PrivateScope, Public, Virtual, HideBySig, VtableLayoutMask
for override - PrivateScope, Public, Virtual, HideBySig
Update 2:
I googled about VtableLayoutMask and came back to StackOverflow
Udate 3:
resulting code:
public static class MethodInfoExtensions
{
public static bool IsOverriden(this MethodInfo method)
{
Contract.Requires<ArgumentNullException>(method != null, "method");
return method.IsVirtual
&& !method.IsStatic
// overriden exactly in this class
&& method.ReflectedType == method.DeclaringType
// not new and not declared for the first time in the class
&& method.GetBaseDefinition() != method;
}
}
Update: The documentation seems to imply that IsHideBySig is the answer, but it does not appear to be the case in practice.
Another strategy is to rely on the presence of the NewSlot attribute:
public static bool HasNewModifier(this MethodInfo method)
{
return (method.Attributes & MethodAttributes.VtableLayoutMask)
== MethodAttributes.NewSlot;
}
Original, incorrect answer follows.
You can rely on the IsHideBySig property. It will be true if the method has the new modifier.
Note the above only applies to C# methods. The documentation elaborates with:
When a member in a derived class is declared with the C# new modifier
or the Visual Basic Shadows modifier, it can hide a member of the same
name in the base class. C# hides base class members by signature. That
is, if the base class member has multiple overloads, the only one that
is hidden is the one that has the identical signature. By contrast,
Visual Basic hides all the base class overloads. Thus, IsHideBySig
returns false on a member declared with the Visual Basic Shadows
modifier, and true on a member declared with the C# new modifier.
The DeclaringType will be different if it was hidden with new. For example, run:
public class A
{
public virtual void WillBeInheritted()
{
}
public virtual void WillBeOverridden()
{
}
public virtual void WillBeHidden()
{
}
}
public class B : A
{
public override void WillBeOverridden()
{
}
public virtual new void WillBeHidden()
{
}
}
class Program
{
public static void Main(string[] args)
{
foreach(var meth in typeof(B).GetMethods())
{
Console.Write(meth.Name);
Console.Write(": ");
Console.Write(meth.GetBaseDefinition().DeclaringType.Name);
Console.Write(" ");
Console.WriteLine(meth.DeclaringType.Name);
}
Console.Read();
}
}
The output will be:
WillBeOverridden: A B
WillBeHidden: B B
WillBeInheritted: A A
WillBeHidden: A A
ToString: Object Object
Equals: Object Object
GetHashCode: Object Object
GetType: Object Object
WillBeInheritted has A as the declaring type for both the method and the base definition's declaring type.
WillBeOverridden has A for the base definition's declaring type, B for the declaring type.
WillBeHidden has two versions, the hidden one in A and the hiding one in B. This makes sense when we consider:
B b = new B();
A a = b;
b.WillBeHidden(); // calls hiding method.
a.WillBeHidden(); // calls hidden method on same object.
You can use GetBaseDefinition to find out where this method was first declared.
For example if you let var mi = typeof(B).GetMethod("Doit"); you can check if mi.GetBaseDefinition() == mi or if mi.GetBaseDefinition().DeclaringType == typeof(B) etc.
Here is an example:
class Animal : object
{
public virtual void M()
{
}
}
class Mammal : Animal
{
public override void M()
{
}
}
class Giraffe : Mammal
{
}
static class Test
{
internal static void Run()
{
var mi = typeof(Giraffe).GetMethod("M");
Console.WriteLine(mi.ReflectedType); // Giraffe
Console.WriteLine(mi.DeclaringType); // Mammal
Console.WriteLine(mi.GetBaseDefinition().DeclaringType); // Animal
}
}
The MethodInfo instance mi represents the override as inherited (unchanged) to Giraffe. And mi.GetBaseDefinition() fetches another MethodInfo which represents instead the method Animal.M which does not carry the override keyword in the C# source.

Why is base class method called instead of derived class method?

Expecting "Hello from the derived." but getting "Hello from the base.".
class Program
{
interface IBase
{
void Method();
}
public class Base: IBase
{
public virtual void Method()
{
Console.WriteLine("Hello from the base.");
}
}
public class Derived : Base
{
public virtual new void Method()
{
Console.WriteLine("Hello from the derived.");
}
}
static void Main(string[] args)
{
IBase x = new Derived();
x.Method();
}
}
So why isn't the derived class's method called. And more importantly, how can I get the derived classes method to get called without casting x to the Derived type?
In my actual application, IBase has several other related methods and Derived only replaces two of the methods in IBase.
When you use the new modifier you are specifically saying that the method is not part of the virtual dispatch chain for that hierarchy, so calling the method by the same name in the base class will not result in redirection to the child class. If you mark the method with override instead of new then you will see the virtual dispatch that you are expecting to see.
You will also need to remove virtual from the derived class's method as you cannot mark an override method as virtual (it already is).
If you really don't want to override the method then it may be more appropriate, in your situation, to not use inheritance at all. You may simply want to use interfaces exclusively:
public interface IFoo
{
void Foo();
}
public class A : IFoo
{
public void Foo()
{
Console.WriteLine("I am A, hear me roar!");
}
}
public class B : IFoo
{
public void Foo()
{
Console.WriteLine("I am B, hear me roar!");
}
}
private static void Main(string[] args)
{
IFoo foo = new A();
foo.Foo();
foo = new B();
foo.Foo();
Console.WriteLine();
Console.WriteLine("Press any key to exit . . .");
Console.ReadKey(true);
}
This is basic polymorphism at work.
For the behavior you're looking for, you would need to set your derived method to override the inherited method:
public class Derived : Base
{
public override void Method()
{
Console.WriteLine("Hello from the derived.");
}
}
Use the override keyword instead of virtual new in your child class.
Therefore, your code should look like:
class Program
{
interface IBase
{
void Method();
}
public class Base: IBase
{
public virtual void Method()
{
Console.WriteLine("Hello from the base.");
}
}
public class Derived : Base
{
public override void Method() // The magic happens here!
{
Console.WriteLine("Hello from the derived.");
}
}
static void Main(string[] args)
{
IBase x = new Derived();
x.Method();
}
}
As described here, the new keyword is used to hide the parent method, which is not what you're looking for.
new keyword creates a new method and says that the base method is hidden. But it is only for consumers of your derived class, since the base class code does not know anything about it.
override keyword overrides the base class implementation with a new one.
class Program
{
interface IBase
{
void Method();
}
public class Base: IBase
{
public virtual void Method()
{
Console.WriteLine("Hello from the base.");
}
}
public class Derived : Base
{
// the next line was changed.
public override void Method()
{
Console.WriteLine("Hello from the derived.");
// note that if you want to call the original implementation, you do it like this:
base.Method();
}
}
static void Main(string[] args)
{
Base x = new Derived();
x.Method();
}
}
The new'd Method in Derived only exists in a Derived instance, where it effectively hides the base implementation.
But IBase type only knows the Base's implementation, so it calls that.
To answer your question, to call the derived's implementation you'd do:
Derived d = new Derived();
d.Method();
((IBase)d).Method();
//Prints:
//Hello from the derived.
//Hello from the base.

Why does Java and C# differ in oops?

1) Why does the following codes differ.
C#:
class Base
{
public void foo()
{
System.Console.WriteLine("base");
}
}
class Derived : Base
{
static void Main(string[] args)
{
Base b = new Base();
b.foo();
b = new Derived();
b.foo();
}
public new void foo()
{
System.Console.WriteLine("derived");
}
}
Java:
class Base {
public void foo() {
System.out.println("Base");
}
}
class Derived extends Base {
public void foo() {
System.out.println("Derived");
}
public static void main(String []s) {
Base b = new Base();
b.foo();
b = new Derived();
b.foo();
}
}
2) When migrating from one language to another what are the things we need to ensure for smooth transition.
The reason is that in Java, methods are virtual by default. In C#, virtual methods must explicitly be marked as such.
The following C# code is equivalent to the Java code - note the use of virtual in the base class and override in the derived class:
class Base
{
public virtual void foo()
{
System.Console.WriteLine("base");
}
}
class Derived
: Base
{
static void Main(string[] args)
{
Base b = new Base();
b.foo();
b = new Derived();
b.foo();
}
public override void foo()
{
System.Console.WriteLine("derived");
}
}
The C# code you posted hides the method foo in the class Derived. This is something you normally don't want to do, because it will cause problems with inheritance.
Using the classes you posted, the following code will output different things, although it's always the same instance:
Base b = new Derived();
b.foo(); // writes "base"
((Derived)b).foo(); // writes "derived"
The fixed code I provided above will output "derived" in both cases.
The C# code will compile with warnings, since you are hiding methods there.
In Java, class-methods are always virtual, whereas in C# they're not, and you have to mark them explicitly as 'virtual'.
In C#, you'll have to do this:
public class Base
{
public virtual void Foo()
{
Console.WriteLine ("Base");
}
}
public class Derived : Base
{
public override void Foo()
{
Console.WriteLine ("Derived.");
}
}

Calling the overridden method from the base class in C#

Given the following C# class definitions and code:
public class BaseClass
{
public virtual void MyMethod()
{
...do something...
}
}
public class A : BaseClass
{
public override void MyMethod()
{
...do something different...
}
}
public class B : BaseClass
{
public override void MyMethod()
{
...do something different...
}
}
public class AnotherObject
{
public AnotherObject(BaseClass someObject)
{
someObject.MyMethod(); //This calls the BaseClass method, unfortunately.
}
}
I would like to call the MyMethod() that is actually found in A or B, assuming the object passed in is actually an instance of A or B, not that which is found in BaseClass. Short of doing something like this:
public class AnotherObject
{
public AnotherObject(BaseClass someObject)
{
A temp1 = someObject as A;
if (A != null)
{
A.MyMethod();
}
B temp2 = someObject as B;
if (B != null)
{
B.MyMethod();
}
}
}
How can I do it?
Which method is called is determined via polymorphism on the type that is passed into the AnotherObject constructor:
AnotherObject a = new AnotherObject(new A()); // invokes A.MyMethod()
AnotherObject b = new AnotherObject(new B()); // invokes B.MyMethod()
AnotherObject c = new AnotherObject(new BaseClass()); //invokes BaseClass.MyMethod()
Sorry, but you are completely mistaken; this would go against the entire point of virtual methods. If someObject is an A then A.MyMethod will be invoked. If someObject is a B then B.MyMethod will be invoked. If someObject is a BaseClass and not an instance of a type derived from BaseClass then BaseClass.MyMethod will be invoked.
Let's use everyone's favorite example:
class Animal {
public virtual void Speak() {
Console.WriteLine("i can haz cheezburger?");
}
}
class Feeder {
public void Feed(Animal animal) { animal.Speak(); }
}
class Cat : Animal {
public override void Speak() { Console.WriteLine("Meow!"); }
}
class Dog : Animal {
public override void Speak() { Console.WriteLine("Woof!"); }
}
Then:
Animal a = new Animal();
Animal c = new Cat();
Animal d = new Dog();
Feeder f = new Feeder();
f.Feed(a);
f.Feed(c);
f.Feed(d);
This will print:
i can haz cheezburger?
Meow!
Woof!
Again, this is the entire point of virtual methods.
Further, we can go to the specification. From 10.6.3 (Virtual methods)
In a virtual method invocation, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke.
(Bolding and italics in original.)
In precise terms, when a method named N is invoked with an argument list A on an instance with a compile-time type C and a run-time type R (where R is either C or a class derived from C), the invocation is processed as follows:
• First, overload resolution is applied to C, N, and A, to select a specific method M from the set of methods declared in and inherited by C. This is described in §7.5.5.1.
• Then, if M is a non-virtual method, M is invoked.
• Otherwise, M is a virtual method, and the most derived implementation of M with respect to R is invoked.
(Bolding not in original.)
Then, we need the definition of "most derived implementation of M." This is a nice recursive definition:
The most derived implementation of a virtual method M with respect to a class R is determined as follows:
• If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
• Otherwise, if R contains an override of M, then this is the most derived implementation of M.
• Otherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to the direct base class of R.
Thus, in our example above with Cat : Animal and Dog : Animal, when the parameter a to Feeder.Feed(Animal) is an instance of Cat then Cat.Speak is the most derived implementation. This is why we will see "Meow!" and not "i can haz cheezburger?"
If MyMethod() is abstract on the base class, then the version in the derived classes will be used. So if you don't need to call the instance in the base class, this would be an option.
static void Main(string[] args)
{
A classA = new A();
B classB = new B();
DoFunctionInClass(classA);
DoFunctionInClass(classB);
DoFunctionInClass(classA as BaseClass);
Console.ReadKey();
}
public static void DoFunctionInClass(BaseClass c)
{
c.MyMethod();
}
public abstract class BaseClass
{
public abstract void MyMethod();
}
public class A : BaseClass
{
public override void MyMethod()
{
Console.WriteLine("Class A");
}
}
public class B : BaseClass
{
public override void MyMethod()
{
Console.WriteLine("Class B");
}
}
If someObject passed in is class A, then A.MyMethod is called, not the base class implementation. Also look at the is keyword.
Because you've typed it as a BaseClass instead of an A or a B, the baseclass is the begin point for the method calls.
You might try using a generic:
public class AnotherObject
{
public AnotherObject<T>(T someObject) where T : BaseClass
{
someObject.MyMethod(); //This calls the BaseClass method, unfortunately.
}
}
I'm not sure how well this will fly in the constructor, but you might be able to move this to a different method.

Categories