Is there a way to specify scope? - c#

Consider this code sample:
public abstract class Parent
{
public int val;
public Parent()
{
val = 0;
}
public virtual void foo()
{
inc();
}
public virtual void inc()
{
val = val + 10;
}
}
public class Child : Parent
{
public override void foo()
{
base.foo();
}
public override void inc()
{
val++;
}
}
static void Main(string[] args)
{
Parent p = new Child();
Console.WriteLine("p.val = " + p.val); //Output: p.val = 0
p.foo();
Console.WriteLine("P.val = " + p.val); //Output: p.val = 1
}
I am assuming the inc() of the Parent class did not get called because {this} pointer is actually pointing to a Child object so the Child's version of inc() will be called from the Parent object's function foo(). Is there a way to force the Parent's function foo() to always call parent's function inc() Like you could in C++ with :: operator?

No, the only way you can call a virtual method non-virtually is with base.Foo. Of course, you could write a non-virtual method in Parent, and make Parent.foo() call that, as well as the default implementation of Parent.inc().

You're over-thinking the problem.
If you want non-virtual dispatch then don't make the methods virtual in the first place.
If you want both virtual and non-virtual dispatch then make two methods, one virtual and one static
For example:
class Base
{
protected static void NonVirtualFoo(Base b)
{
// Whatever
}
public virtual void Foo()
{
Base.NonVirtualFoo(this);
}
}
class Derived : Base
{
protected new static void NonVirtualFoo(Derived d)
{
// Whatever
}
public override void Foo()
{
Derived.NonVirtualFoo(this);
Base.NonVirtualFoo(this);
}
}
Use the right tool for the job. If you want virtual dispatch then call a virtual method. If you want static dispatch then call a static method. Don't try to take a hammer to a virtual method and make it statically dispatched; that's working against the entire purpose of the tool.

The Child instance will call its own type implementation.
foo() calls base.foo() and base.foo() calls inc(), which in this case inc() is from the Child, since the instance is Child type, and will use this implementation.

Well, it is actually possible as said here:
This does the trick:
public abstract class Parent
{
public int val;
public Parent()
{
val = 0;
}
public virtual void foo()
{
MethodInfo method = typeof(Parent).GetMethod("inc");
DynamicMethod dm = new DynamicMethod("BaseInc", null, new Type[] { typeof(Parent) }, typeof(Parent));
ILGenerator gen = dm.GetILGenerator();
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, method);
gen.Emit(OpCodes.Ret);
var BaseInc = (Action<Parent>)dm.CreateDelegate(typeof(Action<Parent>));
BaseInc(this);
}
public virtual void inc()
{
val = val + 10;
}
}
But it's only a proof of concept: it's horrible and totally breaks the polymorphism.
I don't think you can have a valid reason to write this.

Related

Call base method from the base class

To remove complexity let me explain it using the below code snippet.
I want to call the parent's sum method. Now this code will call recursively and end up in stackoverflow error
public class Program
{
public static void Main()
{
var chd_obj = new child();
chd_obj.x = 10;
chd_obj.y=20;
chd_obj.sum();
}
class parent {
public int x {get;set;}
public int y {get;set;}
public virtual void sum(){
Console.WriteLine("From Base" + x+y);
}
public virtual void DoSum(){
this.sum(); // this should call the sum method in the parent class .
//But it is calling the child *sum* method
}
}
class child:parent {
public override void sum(){
base.DoSum();
}
}
}
I don't know if there is a better solution, but I would declare a private method that both sum in the base class and DoSum in the base class call:
private void SumImpl() {
Console.WriteLine("From Base" + x+y);
}
public virtual void sum(){
SumImpl();
}
public virtual void DoSum(){
SumImpl();
}
You get in infinite loop cause child class call Dosum method in Base class and again Dosum from base call child class that's why you see StackOverflow exception.
you should define what sum you mean to the compiler so the derived class can not be called again from the base class for many times.
static void Main(string[] args)
{
child sample = new child();
sample.x = 20;
sample.y = 15;
sample.sum();
Console.ReadLine();
}
public class parent
{
public int x { get; set; }
public int y { get; set; }
public virtual void sum()
{
Console.WriteLine("From Base " + (x + y));
}
public virtual void DoSum()
{
parent a = new parent();
a.x = this.x;
a.y = this.y;
a.sum();
}
}
class child : parent
{
public override void sum()
{
base.DoSum();
}
}
In this way, there is no need to create new methods but you create new instance from your parent class.
You can't do this in C#. There are workarounds, depending on your actual application.
In general, the solution requires you to extract the base's functionality into one or more non-virtual methods.
private void SumCore()
{
// Do stuff.
}
public virtual void Sum()
{
SumCore();
}

Method call with C# dynamic in inherited type

I have noticed an unexpected behavior while trying to extend a base class. Here is a sample for this problem:
public class Program
{
static void Main(string[] args)
{
var test = new CoolProgram();
test.Start();
}
private void Start()
{
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
foreach (var dyn in arr.Cast<dynamic>())
{
DoSomething(dyn);
}
Console.ReadKey();
}
protected virtual void DoSomething(int i)
{
Console.WriteLine("Int:" + i);
}
protected virtual void DoSomething(string str)
{
Console.WriteLine("Str:" + str);
}
}
The Program defines two methods DoSomething which are overloaded by int and string arguments. The Start method creates an array of objectwhich contains boxed values. After the definition, the elements will be iterated with casteddynamic`. This works fine so far (without the long value).
If I create an additional inherited class CoolProgram and add another method to the type for long the program will throw an RuntimeBinderException and tells me that the best overload was DoSomething(int). The method of CoolProgram was not executed.
public class CoolProgram : Program
{
protected override void DoSomething(int i)
{
// This works
Console.WriteLine("Cool Int: " + i);
}
protected override void DoSomething(string str)
{
// This works
Console.WriteLine("Cool Str: " + str);
}
protected virtual void DoSomething(long i)
{
// This is a new method for long
Console.WriteLine("Long:" + i);
}
}
Can anybody explain this behavior or have a solution for it?
Your example can be simplified further:
static void Main(string[] args)
{
Program test = new CoolProgram();
dynamic i = 1L;
test.DoSomething(i);
//test.Start();
}
The issue is that as far as the Start() method is concerned, this has the type Program. Adding a virtual overload for DoSomething() means nothing in the context of the Start() method.
Likewise in my simplified example above. The compile-time type of test is Program, just as the type of this in Start() is Program. Thus, the DoSomething(long) overload is not visible in that context, and can't be called.
If you want it to be visible, you need to either add it to the base class, or make sure that the reference used to call DoSomething() is statically typed as CoolProgram. Note that since the method is declared as protected in CoolProgram, you'd also have to change the accessibility, if you want to go the route of changing the static type of the reference to CoolProgram.
Finally, if you really want fully dynamic type resolution here, you can:
private void Start()
{
dynamic this2 = this;
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
foreach (var dyn in arr.Cast<dynamic>())
{
this2.DoSomething(dyn);
}
Console.ReadKey();
}
The above would of course require that DoSomething(long) be made public, as I noted above.
1)first issue is access modifier protected due to which you are not able to access the overloaded method with Long type as a parameter. i changed it to internal now it is accessible.
2) The second issue is you are creating child class CoolProgram object but you are calling parent class DoSomething method you should use test.DoSomething(dyn); and make the child class object global to access it in your Start method.
public class Program
{
static CoolProgram test;
static void Main(string[] args)
{
test = new CoolProgram();
test.Start();
}
private void Start()
{
var arr = new object[]
{
1, // int
1L, // long
"Hello World" // string
};
//test.DoSomething(21474836470);
foreach (var dyn in arr.Cast<dynamic>())
{
test.DoSomething(dyn);
}
Console.ReadKey();
}
protected virtual void DoSomething(int i)
{
Console.WriteLine("Int:" + i);
}
protected virtual void DoSomething(string str)
{
Console.WriteLine("Str:" + str);
}
}
// from here child class
public class CoolProgram : Program
{
protected override void DoSomething(int i)
{
// This works
Console.WriteLine("Cool Int: " + i);
base.DoSomething(i);
}
protected override void DoSomething(string str)
{
// This works
Console.WriteLine("Cool Str: " + str);
}
internal virtual void DoSomething(long i)
{
// This is a new method for long
Console.WriteLine("Long Int:" + i);
}
}

C# Factory Pattern - Base method will always get called

I'm wondering why in the following example does the base method always get called even though I'm overriding it when the Factory Pattern "Builder" returns a new instance of the object?
interface FactoryInter
{
void MakeDetails();
}
class Builder {
public static Builder getObject(string obj)
{
if(obj == "Cont")
{
return new Cont();
}else{
return new Builder();
}
}
public void MakeDetails()
{
Console.WriteLine("I will always get called..");
}
}
class Cont : Builder, FactoryInter {
public void MakeDetails()
{
Console.WriteLine("Hello..");
}
}
public class Test
{
public static void Main()
{
Builder b = new Builder();
b = Builder.getObject("Cont");
b.MakeDetails();
// your code goes here
}
}
Any help would be greatly appreciated
You do not override it. You are hiding it. Method Cont.MakeDetails() is hiding the base class's MakeDetails method. For more details please see the below example:
class Base
{
public void Hidden()
{
Console.WriteLine("Base!");
}
public virtual void Overrideable()
{
Console.WriteLine("Overridable BASE.");
}
}
class Derived : Base
{
public void Hidden()
{
Console.WriteLine("Derived");
}
public override void Overrideable()
{
Console.WriteLine("Overrideable DERIVED");
}
}
Now testing them yields these results:
var bas = new Base();
var der = new Derived();
bas.Hidden(); //This outputs Base!
der.Hidden(); //This outputs Derived
((Base)der).Hidden();
//The above outputs Base! because you are essentially referencing the hidden method!
//Both the below output Overrideable DERIVED
der.Overrideable();
((Base)der).Overrideable();
To override it, mark the base method as virtual and the derived one as override.

Advise on abstraction

I am working on some code whereby I have an abstract class that has a few core properties and a Run(int index) method. I then create new types that inherit this. These new types can have multiple methods that can be called according to the index passed in.
public abstract class BaseClass
{
public abstract void Run(int index);
}
public class Class1 : BaseClass
{
public override void Run(int index)
{
if (index == 0)
{
MethodA();
}
else if (index == 1)
{
MethodB();
}
}
private void MethodA()
{
//do stuff
}
private void MethodB()
{
//do stuff
}
}
I'm just wondering is there a better way to do this. These types and methods would be called from a UI, - a menu click for example. So I might have a class1 and a class2. Class1 might have 3 methods so I could call run(0) ... run(2) on it. Class2 might just have one internal method so I would just call run(0). Maybe I would need to keep a collection of ints with each class I guess as a map to methods. Might also have to add a string to this collection to hold a friendly name for menu items etc..
Can you think of a way to implement this type of mapping while maintaining as much abstraction as possible? Is there a better way to go about this that my current idea?
One way:
You could use an interface instead:
public interface IRunnableSomething {
void Run();
}
public class MyRunnableA :IRunnableSomething
{
public void Run() {
// do stuff
}
}
public class MyRunnableB :IRunnableSomething
{
public void Run() {
// do stuff
}
}
Then in your main class...
public override void Run(IRunnable runnable)
{
runnable.Run();
}
Example of calling it:
myInstanceOfMainClass.Run(new MyRunnableA());
This seems fitting, since you already know what index you were passing in with your original version. This just moves it from int based to interface based (less code too in the end).
Let me explain a bit further so. Here's a slightly more verbose version of what I am trying to do. You can see here that my abstract class has the list of indexes for pointing at the right method in derived classes, and you can see where I am loading types and creating menu items in a UI. I am using this ItemPointer list and passing around ItemPointers to tag properties etc. It all feels a bit wrong somehow.
I wish for the whole thing to be extensible. I might want to add a Class2, Class3 etc all inheriting BaseClass. I might also want to create plugins using BaseClass. Any derived class will have at least one but runable method but will likely have many. So Class1 here is just an example. Does this help explain myself? please go easy on me, I'm learning and that's why I am asking here.
Is what I'm doing here awful? or is it ok? or is there a better way? I guess that's my question. If there is a better way, I'd really appreciate an example. Many thanks to all for the help. It is much appreciated.
public abstract class BaseClass
{
public List<ItemPointer> ItemPointers = new List<ItemPointer>();
public abstract void Run(int index);
}
public class ItemPointer
{
public int Index { get; set; }
public string ClassType { get; set; }
public string UIDescription { get; set; }
}
public class Class1 : BaseClass
{
public Class1()
{
ItemPointers.Add(new ItemPointer { Index = 0, ClassType = this.GetType().Name, UIDescription = "MethodA Description" });
ItemPointers.Add(new ItemPointer { Index = 1, ClassType = this.GetType().Name, UIDescription = "MethodB Description" });
}
public override void Run(int index)
{
if (index == 0)
{
MethodA();
}
else if (index == 1)
{
MethodB();
}
}
private void MethodA()
{
//do stuff
}
private void MethodB()
{
//do stuff
}
}
public class UIForm
{
private List<BaseClass> _baseClasses;
//Formload events load all baseclass types (including plugins via reflection during form init etc. Then call loadUIitems
private void LoadUIItems()
{
foreach (BaseClass bc in _baseClasses)
{
foreach (var p in bc.ItemPointers)
{
ToolStripMenuItem t = new ToolStripMenuItem(p.UIDescription);
t.Click += new EventHandler(WorkerMenu_Click);
t.Tag = p;
actionsToolStripMenuItem.DropDownItems.Add(t);
}
}
}
void WorkerMenu_Click(object sender, EventArgs e)
{
ToolStripMenuItem t = (ToolStripMenuItem)sender;
ItemPointer p = (ItemPointer)t.Tag;
foreach (BaseClass bc in _baseClasses)
{
if (bc.GetType().Name == p.ClassType)
{
bc.Run(p.Index);
}
}
}
}
In your position I might be inclined to try do something like this:
void Main()
{
var a = new Class1();
var b = new Class2();
try
{
a.Run("Foo");
b.Run("Bar", "Yoda");
b.Run("Bat"); // throws exception
}
catch (Exception ex)
{
Console.WriteLine (ex.Message);
}
}
class Base
{
public void Run(string commandName, params object[] args)
{
var method = this.GetType().GetMethod(commandName);
if(method != null)
method.Invoke(this, args);
else
throw new Exception("the command " + commandName + " does not exist on " + this.GetType().Name);
}
}
class Class1 : Base
{
public void Foo()
{
Console.WriteLine ("I am foo");
}
}
class Class2 : Base
{
public void Bar(string str)
{
Console.WriteLine ("I am {0}", str);
}
}
Output:
I am foo
I am Yoda
the command Bat does not exist on Class2

How do i change the call order of nested constructors (child before abstract parent)

The code below throws an exception because the abstract constructor is called before the child constructor.
I need to provide an abstract class to capsule some logic from a different part of the program. However i also need to check if the abstract members are initialised correctly rigth after creation without the childclass having any influence over this.
the compiling example below should illustrate my question.
using System;
namespace Stackoverflow
{
class Program
{
static void Main(string[] args)
{
var x = new Thing(5);
var y = new Child(x);
}
}
class Child : AbstractParent
{
Thing childthing;
public Child(Thing provided) : base(){
childthing = provided;
}
public override void Initialise(){
//Exception is thrown here - childthing is still null
parentthing = childthing.Add(1);
}
}
abstract class AbstractParent
{
protected Thing parentthing;
public AbstractParent(){
Initialise();
AssertThingyNotNull();
}
private void AssertThingyNotNull(){
if (parentthing == null) throw new Exception("Waaa");
}
public abstract void Initialise();
}
class Thing
{
private int i;
public Thing(int i){
this.i = i;
}
public Thing Add(int b){
i += b;
return new Thing(i);
}
}
}
Edit #1:
Is there some way to do this by reflecting into the caller (should be the creator of child rigth?) and then reacting on the end of that call?
Edit #2:
Getting the .ctor that creates the child is easy. Manipulating the methods seems something between impossible and a bad idea.
foreach (StackFrame frame in new StackTrace().GetFrames())
{
Console.WriteLine(frame.GetMethod().Name);
}
You can't, basically. This is why you should avoid calling virtual (or abstract) members from a constructor as far as possible - you could end up with code which is running with an incomplete context. Any variable initializers are executed before the base class constructor is called, but none of the code within the constructor body is.
If you need to perform initialization and only want to do that when the derived class constructor is running, then just call Initialise from the derived class constructor to start with.
You can do something similar to what Microsoft did with InitializeComponent()
then let the children call it whenever it can.
Try this.
Edited = cleaner version.
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
var x = new Thing(5);
var y = new Child(x);
}
}
class Child : AbstractParent
{
public Child(Thing provided)
: base()
{
parentthing = provided;
base.Initialise();
}
}
abstract class AbstractParent
{
protected Thing parentthing;
public AbstractParent()
{
}
private void AssertThingyNotNull()
{
if (parentthing == null) throw new Exception("Waaa");
}
public void Initialise()
{
AssertThingyNotNull();
}
}
class Thing
{
private int i;
public Thing(int i)
{
this.i = i;
}
public Thing Add(int b)
{
i += b;
return new Thing(i);
}
}
}

Categories

Resources