Dynamic type and static type C# - c#

I'm experimenting with C# and I built the following program (see below).
I understand that the dynamic and static type of first is C. For second the dynamic type is also C but the static type is A. Now I wonder where this might come in handy?
I noticed as well (obviously) that visual studio doesn't allow me to call second.CallA().
Now notice that when I call DoA() on all three types of static type, the dynamic type is C. As this is the case, why doesn't this point to that class? If i recall correct (I might be mistaking) in Java a self.methodA() would start looking up the inhertence tree from the caller instance. As it doesn't appear to be like that here. Can I create such behavior or is this a limitation of the language?
public class A
{
public void methodA()
{
Console.WriteLine("I am class A!");
}
public void DoA()
{
Console.Write("The type of this: " + this.GetType() + " - ");
this.methodA();
}
}
public class B : A
{
public void methodA()
{
Console.WriteLine("I am class B!");
}
}
public class C : B
{
public void methodA()
{
Console.WriteLine("I am class C!");
}
}
class Program
{
static void Main(string[] args)
{
C first = new C();
A second = new C();
dynamic third = new C();
//Show the types of both
Console.WriteLine(first.GetType() + "\n" + second.GetType() + "\n" + third.GetType());
first.methodA();
second.methodA();
third.methodA();
first.DoA();
second.DoA();
third.DoA();
Console.ReadLine();
}
Output:
C
C
C
I am class C!
I am class A!
I am class C!
The type of this: C - I am class A!
The type of this: C - I am class A!
The type of this: C - I am class A!

Can I create such behavior or is this a limitation of the language?
You can create such behavior. In order to do so, you need to make your methods virtual. This will give you that behavior, without using dynamic at all.
public class A
{
public virtual void methodA()
{
Console.WriteLine("I am class A!");
}
Then, later:
public class B : A
{
public override void methodA()
{
Console.WriteLine("I am class B!");
}
}
In C#, you must explicitly make your methods virtual. In Java, methods are effectively virtual by default. This isn't a limitation of the language - it's just a difference between the two languages.

Related

Calling a super base class method from a derived class C# [duplicate]

// Cannot change source code
class Base
{
public virtual void Say()
{
Console.WriteLine("Called from Base.");
}
}
// Cannot change source code
class Derived : Base
{
public override void Say()
{
Console.WriteLine("Called from Derived.");
base.Say();
}
}
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
class Program
{
static void Main(string[] args)
{
SpecialDerived sd = new SpecialDerived();
sd.Say();
}
}
The result is:
Called from Special Derived.
Called from Derived. /* this is not expected */
Called from Base.
How can I rewrite SpecialDerived class so that middle class "Derived"'s method is not called?
UPDATE:
The reason why I want to inherit from Derived instead of Base is Derived class contains a lot of other implementations. Since I can't do base.base.method() here, I guess the best way is to do the following?
// Cannot change source code
class Derived : Base
{
public override void Say()
{
CustomSay();
base.Say();
}
protected virtual void CustomSay()
{
Console.WriteLine("Called from Derived.");
}
}
class SpecialDerived : Derived
{
/*
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
*/
protected override void CustomSay()
{
Console.WriteLine("Called from Special Derived.");
}
}
Just want to add this here, since people still return to this question even after many time. Of course it's bad practice, but it's still possible (in principle) to do what author wants with:
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
var ptr = typeof(Base).GetMethod("Say").MethodHandle.GetFunctionPointer();
var baseSay = (Action)Activator.CreateInstance(typeof(Action), this, ptr);
baseSay();
}
}
This is a bad programming practice, and not allowed in C#. It's a bad programming practice because
The details of the grandbase are implementation details of the base; you shouldn't be relying on them. The base class is providing an abstraction overtop of the grandbase; you should be using that abstraction, not building a bypass to avoid it.
To illustrate a specific example of the previous point: if allowed, this pattern would be yet another way of making code susceptible to brittle-base-class failures. Suppose C derives from B which derives from A. Code in C uses base.base to call a method of A. Then the author of B realizes that they have put too much gear in class B, and a better approach is to make intermediate class B2 that derives from A, and B derives from B2. After that change, code in C is calling a method in B2, not in A, because C's author made an assumption that the implementation details of B, namely, that its direct base class is A, would never change. Many design decisions in C# are to mitigate the likelihood of various kinds of brittle base failures; the decision to make base.base illegal entirely prevents this particular flavour of that failure pattern.
You derived from your base because you like what it does and want to reuse and extend it. If you don't like what it does and want to work around it rather than work with it, then why did you derive from it in the first place? Derive from the grandbase yourself if that's the functionality you want to use and extend.
The base might require certain invariants for security or semantic consistency purposes that are maintained by the details of how the base uses the methods of the grandbase. Allowing a derived class of the base to skip the code that maintains those invariants could put the base into an inconsistent, corrupted state.
You can't from C#. From IL, this is actually supported. You can do a non-virt call to any of your parent classes... but please don't. :)
The answer (which I know is not what you're looking for) is:
class SpecialDerived : Base
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
The truth is, you only have direct interaction with the class you inherit from. Think of that class as a layer - providing as much or as little of it or its parent's functionality as it desires to its derived classes.
EDIT:
Your edit works, but I think I would use something like this:
class Derived : Base
{
protected bool _useBaseSay = false;
public override void Say()
{
if(this._useBaseSay)
base.Say();
else
Console.WriteLine("Called from Derived");
}
}
Of course, in a real implementation, you might do something more like this for extensibility and maintainability:
class Derived : Base
{
protected enum Mode
{
Standard,
BaseFunctionality,
Verbose
//etc
}
protected Mode Mode
{
get; set;
}
public override void Say()
{
if(this.Mode == Mode.BaseFunctionality)
base.Say();
else
Console.WriteLine("Called from Derived");
}
}
Then, derived classes can control their parents' state appropriately.
Why not simply cast the child class to a specific parent class and invoke the specific implementation then? This is a special case situation and a special case solution should be used. You will have to use the new keyword in the children methods though.
public class SuperBase
{
public string Speak() { return "Blah in SuperBase"; }
}
public class Base : SuperBase
{
public new string Speak() { return "Blah in Base"; }
}
public class Child : Base
{
public new string Speak() { return "Blah in Child"; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Child childObj = new Child();
Console.WriteLine(childObj.Speak());
// casting the child to parent first and then calling Speak()
Console.WriteLine((childObj as Base).Speak());
Console.WriteLine((childObj as SuperBase).Speak());
}
}
public class A
{
public int i = 0;
internal virtual void test()
{
Console.WriteLine("A test");
}
}
public class B : A
{
public new int i = 1;
public new void test()
{
Console.WriteLine("B test");
}
}
public class C : B
{
public new int i = 2;
public new void test()
{
Console.WriteLine("C test - ");
(this as A).test();
}
}
You can also make a simple function in first level derived class, to call grand base function
My 2c for this is to implement the functionality you require to be called in a toolkit class and call that from wherever you need:
// Util.cs
static class Util
{
static void DoSomething( FooBase foo ) {}
}
// FooBase.cs
class FooBase
{
virtual void Do() { Util.DoSomething( this ); }
}
// FooDerived.cs
class FooDerived : FooBase
{
override void Do() { ... }
}
// FooDerived2.cs
class FooDerived2 : FooDerived
{
override void Do() { Util.DoSomething( this ); }
}
This does require some thought as to access privilege, you may need to add some internal accessor methods to facilitate the functionality.
In cases where you do not have access to the derived class source, but need all the source of the derived class besides the current method, then I would recommended you should also do a derived class and call the implementation of the derived class.
Here is an example:
//No access to the source of the following classes
public class Base
{
public virtual void method1(){ Console.WriteLine("In Base");}
}
public class Derived : Base
{
public override void method1(){ Console.WriteLine("In Derived");}
public void method2(){ Console.WriteLine("Some important method in Derived");}
}
//Here should go your classes
//First do your own derived class
public class MyDerived : Base
{
}
//Then derive from the derived class
//and call the bass class implementation via your derived class
public class specialDerived : Derived
{
public override void method1()
{
MyDerived md = new MyDerived();
//This is actually the base.base class implementation
MyDerived.method1();
}
}
As can be seen from previous posts, one can argue that if class functionality needs to be circumvented then something is wrong in the class architecture. That might be true, but one cannot always restructure or refactor the class structure on a large mature project. The various levels of change management might be one problem, but to keep existing functionality operating the same after refactoring is not always a trivial task, especially if time constraints apply. On a mature project it can be quite an undertaking to keep various regression tests from passing after a code restructure; there are often obscure "oddities" that show up.
We had a similar problem in some cases inherited functionality should not execute (or should perform something else). The approach we followed below, was to put the base code that need to be excluded in a separate virtual function. This function can then be overridden in the derived class and the functionality excluded or altered. In this example "Text 2" can be prevented from output in the derived class.
public class Base
{
public virtual void Foo()
{
Console.WriteLine("Hello from Base");
}
}
public class Derived : Base
{
public override void Foo()
{
base.Foo();
Console.WriteLine("Text 1");
WriteText2Func();
Console.WriteLine("Text 3");
}
protected virtual void WriteText2Func()
{
Console.WriteLine("Text 2");
}
}
public class Special : Derived
{
public override void WriteText2Func()
{
//WriteText2Func will write nothing when
//method Foo is called from class Special.
//Also it can be modified to do something else.
}
}
There seems to be a lot of these questions surrounding inheriting a member method from a Grandparent Class, overriding it in a second Class, then calling its method again from a Grandchild Class. Why not just inherit the grandparent's members down to the grandchildren?
class A
{
private string mystring = "A";
public string Method1()
{
return mystring;
}
}
class B : A
{
// this inherits Method1() naturally
}
class C : B
{
// this inherits Method1() naturally
}
string newstring = "";
A a = new A();
B b = new B();
C c = new C();
newstring = a.Method1();// returns "A"
newstring = b.Method1();// returns "A"
newstring = c.Method1();// returns "A"
Seems simple....the grandchild inherits the grandparents method here. Think about it.....that's how "Object" and its members like ToString() are inherited down to all classes in C#. I'm thinking Microsoft has not done a good job of explaining basic inheritance. There is too much focus on polymorphism and implementation. When I dig through their documentation there are no examples of this very basic idea. :(
I had the same problem as the OP, where I only wanted to override a single method in the middle Class, leaving all other methods alone. My scenario was:
Class A - base class, DB access, uneditable.
Class B : A - "record type" specific functionality (editable, but only if backward compatible).
Class C : B - one particular field for one particular client.
I did very similar to the second part of the OP posting, except I put the base call into it's own method, which I called from from Say() method.
class Derived : Base
{
public override void Say()
{
Console.WriteLine("Called from Derived.");
BaseSay();
}
protected virtual void BaseSay()
{
base.Say();
}
}
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.BaseSay();
}
}
You could repeat this ad infinitum, giving, for example SpecialDerived a BaseBaseSay() method if you needed an ExtraSpecialDerived override to the SpecialDerived.
The best part of this is that if the Derived changes its inheritance from Base to Base2, all other overrides follow suit without needing changes.
If you want to access to base class data you must use "this" keyword or you use this keyword as reference for class.
namespace thiskeyword
{
class Program
{
static void Main(string[] args)
{
I i = new I();
int res = i.m1();
Console.WriteLine(res);
Console.ReadLine();
}
}
public class E
{
new public int x = 3;
}
public class F:E
{
new public int x = 5;
}
public class G:F
{
new public int x = 50;
}
public class H:G
{
new public int x = 20;
}
public class I:H
{
new public int x = 30;
public int m1()
{
// (this as <classname >) will use for accessing data to base class
int z = (this as I).x + base.x + (this as G).x + (this as F).x + (this as E).x; // base.x refer to H
return z;
}
}
}

Polymophism in C#, how to turn parent object into a child object in a method?

public class Program
{
public static void Main()
{
var type = new C().getType();
type.Foo();
}
public class A
{
public void Stop()
{
// do something
}
}
public class B : A
{
public void Foo()
{
Console.WriteLine("Foo");
}
}
public class D : A
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
public class C
{
public A getType()
{
if (some condition)
return new B();
if (some condition)
return new D();
return A();
}
}
}
-EDIT-
I updated the code, so now we have two child classes B and D, both have different methods inside them, however since they inherit A, they at least both have access to Stop() method. The problem with making an abstract method Foo() and Bar() inside the parent class A is that, B should not have access to Bar() and D should not have access to Foo(), but by making an abstract method they will need to implement them both.
I know that I can check the type of the returned object inside Main() method and then cast it to that type. But this won't be convenient as in the future I will have more descendants of A.
Is it in my situation ok, to use dynamic? Because that would solve the problem and would be very convenient.
public class C
{
public dynamic getType()
{
if (some condition)
return new B();
if (some condition)
return new D();
return A();
}
}
You almost had it right:
public class Program
{
public static void Main()
{
var type = new C().getType();
type.Foo();
}
public abstract class A
{
public abstract void Foo();
}
public class B : A
{
public override void Foo()
{
Console.WriteLine("Foo");
}
}
public class C
{
public A getType()
{
return new B();
}
}
}
You need a Foo method in A that B can override. I have made A.Foo abstract, which means we do not have to define a base implementation of A.Foo. The A class is declared abstract to prevent someone trying to create an instance of it.
If you want derived classes to inherit a base implementation of Foo from A, then declare Foo as virtual in A. So in the following example, class B overrides the base Foo, whereas class C inherits the base Foo:
public class Program
{
public static void Main()
{
A a1 = new B();
a1.Foo(); // Outputs "B.Foo".
A a2 = new C();
a2.Foo(); // Outputs "A.Foo".
}
public abstract class A
{
public virtual void Foo()
{
Console.WriteLine("A.Foo");
}
}
public class B : A
{
public override void Foo()
{
Console.WriteLine("B.Foo");
}
}
public class C : A
{
}
}
You are confusing the type of a variable and the type of the runtime object it will be pointing to (given its a reference type, with value types, there is no such distinction).
When you declare a variable, you are defining the type of the variable:
Foo a = ... //a is of type Foo at compile time.
What you assign to that variable doesn't matter at all (unless you are using implicitly typed variables with var)
But given the following code:
object o = new Foo();
Now you can see the diferrence; the variable o is of type object but the runtime object it will be pointing to is of type string.
In your question you are asking why you cant do the following:
var stringLength = o.Length; //o is a string isn't it?
Why? Isn't o really a string. Yes, but that information is only availabe at runtime, the compiler knows nothing of what will happen at runtime, it only knows that o is of type object and object has no Length property. The only thing the compiler will make sure of is that the types are compatible; it will let you assign a Giraffe to an Animal typed variable but it won't let you assing a Car.
If you've got this clear, then you'll understando why this doesn't make sense:
But I did explicitly return B inside getType() method, why does it not have access to Foo()?
Because the method getType return type is A not B, not C and not D.

Calling method based on run-time type insead of compile-time type

In an application, I need .NET to call a method based on its run-time type instead of its compile-time type.
Simplified Example:
class A { }
class B : A { }
static void Main(string[] args)
{
A b = new B();
Print(b);
}
static void Print(A a)
{
Console.WriteLine("Called from A");
}
static void Print(B b)
{
Console.WriteLine("Called from B");
}
The above code will actually print Called from A, but I need it to be Called from B.
This works as expected:
static void Print(A a)
{
var b = a as B;
if (b != null)
return Print(b);
else
Console.WriteLine("Called from A");
}
But for maintainability's sake, it is not desirable.
I believe this question is similar to this one: Why isn't this method chosen based on the runtime-type of its object?, but for .NET instead of Java.
The simplest approach if you're using .NET 4 or higher is to use dynamic typing:
dynamic b = new B();
Print(b);
Almost all expressions using a value of type dynamic will be invoked dynamically, with a "mini-C# compiler" applying the same rules at execution time as it would have done at compile-time, but using the actual execution-time type of those dynamic values. (Expressions whose types are known statically at compile-time will still be regarded as having those types though - it doesn't make everything about overload resolution into dynamic.)
If you're not using .NET 4, it's somewhat harder - you could either use reflection, or hard-code the options, neither of which is fun.
You can make use of the dynamic type:
A b = new B();
dynamic tmp = b;
Print(tmp); // Prints "Called from B"
However, please note that this has the draw back that it will generate a runtime exception instead of a compile error if there is no matching method.
Use overriding of OOP.
Exmaple:
class A {
public virtual void Print() {
Console.WriteLine("Called from A");
}
}
class B : A {
public override void Print() {
Console.WriteLine("Called from B");
}
}
and use it like:
A b = new B();
Print(b);
static void Print(A a)
{
a.Print(); //will run B's method
}
It will run runtime type method, as you use simple overriding concept.
This is not how polymorphism works. You should consider doing something similar to the following instead:
class A
{
virtual string GetString()
{
return "Called from A";
}
}
class B : A
{
override string GetString()
{
return "Called from B";
}
}
static void Main(string[] args)
{
A b = new B();
Print(b);
}
static void Print(A a)
{
Console.WriteLine(a.GetString());
}
try this:
class A
{
public virtual string Print()
{
return "Called from A";
}
}
class B : A
{
public override string Print()
{
return "Called from B";
}
}
And test it elsewhere
A b = new B();
MessageBox.Show(b.Print()); //called from B

Why base keyword can't be used in static methods?

Why we can't use base keyword to use base class methods in static methods?
Both are available at compile time.
class A
{
public virtual void Func(int a=4){
Console.WriteLine(" A Class: "+a);
}
}
class B : A
{
public new void Func(int a = 12)
{
Console.WriteLine(" B Class: "+ a);
}
}
class C : B
{
public static void Func()
{
base.Func(); // why not ????
}
}
public class Program
{
public static void Main(string[] args)
{
B ob = new C();
ob.Func();
Console.ReadLine();
}
}
Because base keyword is referring to the base class of the current class instance. But you do not have a current instance in static methods - they are static not instance.
You will be able to call B.Func() if you made the Func() method static in class B.
The C# Language Specification states in section 10.6.4 Override methods (emphasis mine):
A compile-time error occurs unless all of the following are true for an override declaration:
...
The overridden base method is a virtual, abstract, or override method. In other words, the overridden base method cannot be static or non-virtual.
Theoretically, it might be possible to look at the base class of the referenced type. After all, the inheritance relationship between classes is defined on the type, not the instance. For example, if I have class A: B, when presented with A.Foo(), the compiler could look for a static virtual method in B called Foo after looking in class A or for base in A.Foo() to return a list of static methods in B. However, I suspect this is a compiler optimization and language simplification to avoid having to handle references to a list of static methods only and the confusion it would cause.

Call of overloaded method from generic method issue

I've run into interesting thing (works same in both Java and C#).
Java code:
public class TestStuff {
public static void main(String[] args) {
Printer p = new PrinterImpl();
p.genericPrint(new B());
}
}
class PrinterImpl implements Printer {
void print(A a) {
System.out.println("a");
}
void print(B b) {
System.out.println("b");
}
#Override
public <T extends A> void genericPrint(T b) {
print(b);
}
}
interface Printer {
public <T extends A> void genericPrint(T a);
}
class A {
}
class B extends A{
}
C# code:
namespace TestStuff
{
internal class Program
{
private static void Main(string[] args)
{
var printer = new Printer();
printer.GenericPrint(new B());
}
}
public class Printer
{
public void Print(A a)
{
Console.WriteLine("a");
}
public void Print(B b)
{
Console.WriteLine("b");
}
public void GenericPrint<T>(T a) where T : A
{
Print(a);
}
}
public class B : A
{
}
public class A
{
}
}
When I wrote something like this I expected to see "b" printed in both cases.
But, as you can see, it is "a" what is printed.
I've read C# language specification and it says overloaded method is selected at compile-time. It explains why it works that way.
However, I had no time to check it out in Java language specification.
Could somebody please give a more detailed explanation of what is happening and why? And how could I achieve what I wanted?
Thanks in advance!
The key is to understand that generics are only available at compile time in java. It is just syntax sugar that the compiler uses while compiling, but throws away while generating the class files.
As such, the code:
public <T extends A> void genericPrint(T b) {
print(b);
}
is compiled into:
public void genericPrint(A b) {
print(b);
}
Since the argument to print is of type A, the overloaded version print(A a) is the one resolved. I'd suggest using polymorphic calls on instances of A or the Visitor pattern to callback into PrinterImpl for your use case.
Something like:
interface Visitor {
void visit(A a);
void visit(B b);
}
class PrinterImpl implements Printer, Visitor {
void print(A a) {
System.out.println("a");
}
void print(B b) {
System.out.println("b");
}
public <T extends A> void genericPrint(T b) {
b.accept(this);
}
public void visit(A a) {
print(a);
}
public void visit(B b) {
print(b);
}
}
interface Printer {
public <T extends A> void genericPrint(T a);
}
class A {
public void accept(Visitor v) {
v.visit(this);
}
}
class B extends A {
public void accept(Visitor v) {
v.visit(this);
}
}
Its true that overloaded methods are selected at compile time and its true for java also(dynamic method dispatch).
However Generics works a little differently. Your method GenericPrinter can only work Types A or its derivative. Its a constraint on that method. Suppose in your GenricPrinter class you have invoked a method thats defined in A.
public class A
{
void DoSomethingA()
{
}
}
.
.
.
public void GenericPrint<T>(T a) where T : A
{
//constraint makes sure this is always valid
a.DoSomethingA();
Print(a);
}
So this constraint would make sure that only A or its sub classes, that contains the above method would only be allowed.
Although you pass in an instance of A's subclass but due to constaint, GenericPrinter would treat the subclass as A.
Just remove the constraint part (T:A) and B would be printed as you expect.
There is no runtime check of which type a is in your GenericPrint method. The only thing you enforce with the where T : A part, is that you can call Print.
Btw, apart from that generic method: If you want a to be printed, although it is an instance of B, then you have to declare that variable as A obj = new B().

Categories

Resources