I am quite new to C# and I cannot understand the behaviour of a class in my project.
I am using an interface that defines a generic with a type constraint which is another interface.
When I call the generic, I know that a certain method exists on the argument (because of the type constraint), but this method doesn't get executed when I call it.
The only workaround I have so far is to include the method call into the type-specific method overloads.
This may be better explained with the following snippet with an equivalent type structure:
public interface ITrickable
{
void GetRabbitOut();
}
public interface IMagic
{
void DoTricks<T>(T obj) where T : ITrickable;
}
public class Hat : ITrickable
{
public void LiftUp() { Console.WriteLine("Lifting up the hat..."); }
public void GetRabbitOut() { Console.WriteLine("A rabbit came out the hat !"); }
}
public class Box : ITrickable
{
public void OpenDoubleBottom() { Console.WriteLine("Opening the box..."); }
public void GetRabbitOut() { Console.WriteLine("A rabbit came out the box !"); }
}
public abstract class Magician : IMagic
{
public abstract void DoTricks<T>(T obj) where T : ITrickable;
}
Now if I call DoTricks(new Hat()); DoTricks(new Box()); with the class below:
public class Houdini : Magician
{
public override void DoTricks<T>(T obj)
{
try {
DoTricks(obj); }
catch {
throw new NotImplementedException(); }
}
public void DoTricks(Hat obj)
{
obj.LiftUp();
obj.GetRabbitOut();
}
public void DoTricks(Box obj)
{
obj.OpenDoubleBottom();
obj.GetRabbitOut();
}
}
The output is as expected:
Lifting up the hat...
A rabbit came out the hat !
Opening the box...
A rabbit came out the box !
But if the class is defined as this one below:
public class Genesta : Magician
{
public override void DoTricks<T>(T obj)
{
try {
DoTricks(obj);
obj.GetRabbitOut(); } // <--- This seems to be ignored !?
catch {
throw new NotImplementedException(); }
}
public void DoTricks(Hat obj)
{
obj.LiftUp();
}
public void DoTricks(Box obj)
{
obj.OpenDoubleBottom();
}
}
The output is
Lifting up the hat...
Opening the box...
The question is why does GetRabbitOut is not called in the second class?
EDIT: The calling code is:
public static void Main(string[] args)
{
var houdini = new Houdini();
var hat = new Hat();
var box = new Box();
houdini.DoTricks(hat);
houdini.DoTricks(box);
Console.ReadLine();
}
Notice your method calls (I imagine it looked something resembling this):
Genesta g = new Genesta();
g.DoTricks(new Hat());
g.DoTricks(new Box());
Since you call g.DoTricks(new Hat()) rather than g.DoTricks<Hat>(new Hat()), no surprises that the exact method of the Genesta class that is invoked is DoTricks(T obj) and not DoTricks<T>(T obj). And when considering the implementation of DoTricks(T obj)...
public void DoTricks(Hat obj)
{
obj.LiftUp();
}
public void DoTricks(Box obj)
{
obj.OpenDoubleBottom();
}
The result is actually what you can expect from these methods!
If, however, you would call the generic method like this...
g.DoTricks<Hat>(new Hat());
You would fall into an infinite recursion, as the method would call itself indefinitely. DoTricks<T>(T obj) will always call itself and not one of the specialized overloads DoTricks(Hat) or DoTricks(Box), since the compiler cannot know before runtime that T will in fact be either Hat or Box.
By the way, the Houdini class experiences the same effect - it just so happens that its specific DoTricks(Hat) and DoTricks(Box) methods produce the result that you expected from calling DoTricks<T>(T obj).
Related
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.
Is it possible in C# to overload a method with different signatures in different descendants of a base class, and then call the appropriate method based on the runtime type of an argument to the overloaded method?
As background, I'm working on message handling process, starting from a point where the message type not known at compile time, and with different message handling functionality intended to be added for different types over time. Ideally new message handling would change the subclass but not the base class. It works fine now by including all typed methods in the base class and explicitly selecting the correct one based on the message type. The question is driven mainly by curiosity since based on the answer to this question I expect it should be possible. If I'm overcomplicating this and theres a simpler approach I'd welcome that advice too.
Example code showing this is below, I expected HandleTypedMessage(BaseMessage msg) and HandleTypedMessage(MessageA msg) to be called once each, instead HandleTypedMessage(BaseMessage msg) is called twice.
class Program
{
static void Main(string[] args)
{
var msga = new MessageA();
var msgb = new MessageB();
MessageHandler handlerA = new MessageHandlerA();
handlerA.HandleTypedMessage((dynamic) msga);
handlerA.HandleTypedMessage((dynamic) msgb);
Console.ReadLine();
}
}
public interface IHandlesMessage
{
void HandleMessage(BaseMessage message);
}
public abstract class BaseMessage
{
public abstract string MessageType { get; }
}
public class MessageA : BaseMessage
{
public override string MessageType
{
get { return "http://message/a"; }
}
}
public class MessageB : BaseMessage
{
public override string MessageType
{
get { return "http://message/a"; }
}
}
public abstract class MessageHandler
{
public abstract void HandleTypedMessage(BaseMessage msg);
}
public class MessageHandlerA : MessageHandler
{
public override void HandleTypedMessage(BaseMessage msg)
{
Console.WriteLine("Did nothing with " + msg.MessageType);
}
public void HandleTypedMessage(MessageA msg)
{
Console.WriteLine("Handled message a");
}
}
public class MessageHandlerB : MessageHandler
{
public override void HandleTypedMessage(BaseMessage msg)
{
throw new NotImplementedException();
}
public void HandleTypedMessage(MessageB msg)
{
System.Console.WriteLine("Handled message b");
}
}
You're making incorrect part of your method invocation dynamic. Make the target dynamic, not the parameter:
((dynamic)handlerA).HandleTypedMessage(msga);
((dynamic)handlerA).HandleTypedMessage(msgb);
It will look for best matching HandleTypedMessage method for actual type handlerA points to (MessageHandlerA), not the one it's declared as (MessageHandler).
Code above prints
Handled message a
Did nothing with http://message/a
One approach is to move the dynamic dispatch into the handler sublcasses like this:
public class MessageHandlerA : MessageHandler {
public override void HandleTypedMessage(BaseMessage msg) {
this.HandleTypedMessageCore((dynamic) msg);
}
private void HandleTypedMessageCore(BaseMessage msg) {
Console.WriteLine("Did nothing with " + msg.MessageType);
}
private void HandleTypedMessageCore(MessageA msg) {
Console.WriteLine("Handled message a");
}
}
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
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);
}
}
}
Suppose you had such code:
public Base
{
abstract void Register();
}
public Registrator1: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
public Registrator2: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
But When you receive a new business rule asking you to write Registrator3 which actually registers based on some parameter and you change your code base to the next:
public Base
{
abstract void Register(externalParam);
}
public Registrator1: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate theUI
}
}
public Registrator2: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate the UI
}
}
public Registrator3: Base
{
override void Register(externalParam)
{
//uses a DDD - service passed in the params to populate the UI
}
}
But Registrator1 and Registrator2 do not need that param and the code becomes smelly. What are the ways to re-write this code?
You could use an object as a parameter here; which is commonly used in scenarios where the number of parameters can vary depending on the call being used.
struct RegistrationInfo
{
public static readonly RegistrationInfo Empty = new RegistrationInfo();
public string Username;
public string CustomerName;
public string Validity;
}
abstract class Base
{
public abstract void Register(RegistrationInfo info);
// If you want to retain the paramaterless call:
public void Register()
{
Register(RegistrationInfo.Empty);
}
}
class Registrar1 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.Username == null) throw new ArgumentNullException("info.Username");
}
}
class Registrar2 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.CustomerName == null) throw new ArgumentNullException("info.CustomerName");
}
}
This has the advantage that you don't need to change method parameters (which is breaking interface) each time a parameter is added. The usage also becomes somewhat self-documenting:
var r = new Registrar1();
r.Register(new RegistrationInfo(){ Username = "JimJoe" });
r.Register(RegistrationInfo.Empty);
It's like air freshener for this type of code smell, while it's still smelly; you can make it smell nicer.
Finally you can make the call-site cleaner by making it a params argument (this has a small amount of overhead); in all honesty though it is more smelly because it's a language hack. Finally you could improve it with generics:
class RegistrationInfo
{
}
class RegistrationInfo1 : RegistrationInfo
{
public string Arg;
}
class RegistrationInfo2 : RegistrationInfo
{
public int Arg;
}
interface IBase<in TRegistration>
where TRegistration : RegistrationInfo
{
void Register(TRegistration registration);
}
class Base : IBase<RegistrationInfo>
{
public void Register(RegistrationInfo registration)
{
}
}
class Registrar1 : IBase<RegistrationInfo1>
{
public void Register(RegistrationInfo1 arg)
{
}
}
class Registrar2 : IBase<RegistrationInfo2>
{
public void Register(RegistrationInfo2 arg)
{
}
}
Is it not possible to contain the logic for externalParam in Registrator3?
In other words, Registrator3 uses the param, then calls the unmodified parameterless base?
A lot really depends on where the logic belongs. If it is something intrinsic to the base, then put it in the base, and either overload the Register() function or supply a default value for the param so that sub classes don't need to provide it.
Assuming you want to reuse the registration logic from the base class, you could update the code as follows:
public class Base
{
public virtual void Register(object externalParam)
{
// base registration logic goes here
}
}
public class Registrator1: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator2: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator3: Base
{
public override void Register(object externalParam)
{
base.Register(externalParam);
// custom registration logic goes here
}
}
HTH,
Cosmin
EDIT: Updated code to compile.