How to force covariance when resolving function overload? - c#

In C# I can do this:
public class BaseClass { };
public class A : BaseClass
{
public void Foo(){ Console.WriteLine("A"); }
};
public class B : BaseClass
{
public void Bar(){ Console.WriteLine("B"); }
};
public static void SwitchThingy(BaseClass obj){
Console.WriteLine("Default case");
}
public static void SwitchThingy(A obj){
obj.Foo();
}
public static void Main()
{
A a = new A();
B b = new B();
SwitchThingy(a);
SwitchThingy(b);
}
It will output
A
Default case
However, if I change Main() to
public static void Main()
{
A a = new A();
B b = new B();
List<BaseClass> myList = new List<BaseClass>();
myList.Add(a);
myList.Add(b);
SwitchThingy(myList[0]);
SwitchThingy(myList[0]);
}
Then output changes to
Default case
Default case
Which makes sense since no conversion is required for that overload and so it is preferred over the other which does require extra work.
How can I force the overload for the derived class to be called instead, like in the first case, but after putting the objects into a List?
All I want to avoid here is to have several subclasses (A, B, ...) implementing boilerplate code if possible as well as keep the implementation of SwitchThingy outside of the classes.

As soon as you put the objects in a list of the base class type, the compiler will not any longer be able to help you. Decisions based on the actual type will then have to be made explicitly at runtime in your code.
One possible and classic approach to solve your problem is using the visitor pattern:
This way you only have to implement one "Accept" method in each of your classes. You can then create concrete Visitor classes to decide how to handle the different classes.
class Program
{
public class BaseClass
{
public virtual void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public class A : BaseClass
{
public void Foo() { Console.WriteLine("A"); }
public override void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public class B : BaseClass
{
public void Bar() { Console.WriteLine("B"); }
public override void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public class C : BaseClass
{
public override void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public interface IBaseClassVisitor
{
void Visit(BaseClass obj);
void Visit(A obj);
void Visit(B obj);
void Visit(C obj);
}
public class SwitchThingyVisitor : IBaseClassVisitor
{
public void Visit(BaseClass obj)
{
Console.WriteLine("Default case");
}
public void Visit(A obj)
{
obj.Foo();
}
public void Visit(B obj)
{
obj.Bar();
}
public void Visit(C obj)
{
// refer to default implementation
Visit((BaseClass)obj);
}
}
public static void Main()
{
A a = new A();
B b = new B();
C c = new C();
List<BaseClass> myList = new List<BaseClass>();
myList.Add(a);
myList.Add(b);
myList.Add(c);
SwitchThingyVisitor visitor = new SwitchThingyVisitor();
foreach (var obj in myList)
{
obj.Accept(visitor);
}
Console.ReadLine();
}
}
A much simpler approach is having a routing function that does an explicit runtime check of the types and calls the respective functions. Newer c# versions allow using a concise syntax by using pattern matching:
class Program
{
public class BaseClass
{
};
public class A : BaseClass
{
public void Foo() { Console.WriteLine("A"); }
};
public class B : BaseClass
{
public void Bar() { Console.WriteLine("B"); }
};
public class C : BaseClass
{
};
public static void RouteSwitchThingy(BaseClass obj)
{
switch (obj)
{
case A a:
SwitchThingy(a);
break;
case B b:
SwitchThingy(b);
break;
default:
SwitchThingy(obj);
break;
}
}
public static void SwitchThingy(BaseClass obj)
{
Console.WriteLine("Default case");
}
public static void SwitchThingy(A obj)
{
obj.Foo();
}
public static void SwitchThingy(B obj)
{
obj.Bar();
}
public static void Main()
{
A a = new A();
B b = new B();
C c = new C();
List<BaseClass> myList = new List<BaseClass>();
myList.Add(a);
myList.Add(b);
myList.Add(c);
foreach (var obj in myList)
{
RouteSwitchThingy(obj);
}
Console.ReadLine();
}
}

Related

C# base class extension is called instead of the one for a derived class [duplicate]

This question already has an answer here:
Inheritance and extension method
(1 answer)
Closed last year.
I have class A which is a base class for B. And an extension for both types. Then if I call an extension from a generic function (even with an object of type B) it still calls an extension for a base class
void Main()
{
var b = new B();
GenericClass.SomeGenericFunction<B>(b);
}
public class A
{
public void fooA()
{
Console.WriteLine("A");
}
};
public class B : A
{
public void fooB()
{
Console.WriteLine("B");
}
};
public static class Extension {
public static void SomeMethod(this A a)
{
a.fooA();
}
public static void SomeMethod(this B b)
{
b.fooB();
}
};
public static class GenericClass {
public static void SomeGenericFunction<T>(T someObject) where T : A, new()
{
someObject.SomeMethod();
}
};
The question basically is why the result is?
A
Generic method for reference types shares implementation for all reference types so compiler will resolve SomeMethod only one time during compilation - for "highest" class in hierarchy - A. You can workaround that either by changing A (and B) by making SomeMethod an virtual instance method of A hierarchy or using type checks in your generic function:
public static class GenericClass
{
public static void SomeGenericFunction<T>(T someObject) where T : A, new()
{
switch (someObject)
{
case B b:
b.SomeMethod();
break;
case A:
default:
someObject.SomeMethod();
break;
}
}
}
Or diving into reflection.
try this
public class A
{
public virtual void foo()
{
Console.WriteLine("A");
}
};
public class B : A
{
public override void foo()
{
Console.WriteLine("B");
}
};
public static class Extension
{
public static void SomeMethod(this A a)
{
a.foo();
}
public static void SomeMethod(this B b)
{
b.foo();
}
};
public static class GenericClass
{
public static void SomeGenericFunction<T>(T someObject) where T : A, new()
{
someObject.SomeMethod();
}
};
test
var b = new B();
GenericClass.SomeGenericFunction<B>(b);
result
B
if you need to keep your classes, you can use this code as well. It is easier to extend and mantain. I only don't understand why do you need extensions if you use GenericClass? Maybe it is easier to use as C bellow? Or just use extensions. It seems as they repeat each other.
public static class GenericClass
{
public static void SomeGenericFunction(B someObject)
{
someObject.SomeMethod();
}
public static void SomeGenericFunction(C someObject)
{
someObject.fooC();
}
public static void SomeGenericFunction<T>(T someObject) where T : A, new()
{
someObject.SomeMethod();
}
}

How to inherit two or more interface with same method name and the derived class should be further inherited into another class in C# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
How can we implement two or more interfaces with same method name into the class and the derived class should be further inherit into new class with same methods.
using System;
interface A
{
void Hello();
}
interface B
{
void Hello();
}
class Test : A, B
{
void A.Hello()
{
Console.WriteLine("Test Hello-A");
}
void B.Hello()
{
Console.WriteLine("Test Hello-B");
}
}
class Demo : Test {
//what will be the code to override Hello method
}
public class MainClass
{
public static void Main()
{
//How can we access the Hello method of Test & Demo class
}
}
There are some limitations when working with explicit interface implementations because the methods can't be virtual. But you can do a workaround to resolve this issue by creating more methods that can be virtual and then override them.
I am not too happy with this code but it fully answers your question.
using System;
interface A
{
void Hello();
}
interface B
{
void Hello();
}
class Test : A, B
{
public virtual void HelloA()
{
Console.WriteLine("Test Hello-A");
}
public virtual void HelloB()
{
Console.WriteLine("Test Hello-A");
}
void A.Hello()
{
this.HelloA();
}
void B.Hello()
{
this.HelloB();
}
}
class Demo : Test
{
//what will be the code to override Hello method
public override void HelloA()
{
}
public override void HelloB()
{
}
}
public class MainClass
{
public static void Main()
{
//How can we access the Hello method of Test & Demo class
Test test = new();
test.HelloA();
test.HelloB();
Demo demo = new();
demo.HelloA();
demo.HelloB();
// Another option will be to call it using the interfaces:
List<A> itemsA = new();
itemsA.Add(test);
itemsA.Add(demo);
foreach (A itemA in itemsA)
{
itemA.Hello();
}
List<B> itemsB = new();
itemsB.Add(test);
itemsB.Add(demo);
foreach (B itemB in itemsB)
{
itemB.Hello();
}
}
}
If you have a explicit private implementation as in the code shown, you would need to explicitly implement A and B in Demo again.
class Demo : Test , A, B
{
void A.Hello()
{
Console.WriteLine("Demo Hello-A");
}
void B.Hello()
{
Console.WriteLine("Demo Hello-B");
}
}
However you will, as far as I can see, not be able to invoke the implementations in Test from an instance of Demo, no matter how you'd cast it:
var demo = new Demo();
var a_demo = (A)demo;
var b_demo = (B)demo;
var test = (Test)demo;
var a_test = (A)test;
var b_test = (B)test;
a_demo.Hello();
b_demo.Hello();
a_test.Hello(); //invokes impl in demo
b_test.Hello(); //invokes impl in demo
class Program
{
static void Main()
{
IA objIa = new AB();
objIa.Hello(10,20);
IB objIb = new AB();
objIb.Hello(10,20);
ABC abc = new ABC();
abc.Hello1(10,20);
IA obj = new ABC();
obj.Hello(10,20);
IB obj1 = new ABC();
obj1.Hello(10,20);
Console.ReadLine();
}
}
interface IA
{
void Hello(int a, int b);
}
interface IB
{
void Hello(int a, int b);
}
public class AB : IA, IB
{
void IA.Hello(int a, int b)
{
Console.WriteLine("IA method");
}
void IB.Hello(int a, int b)
{
Console.WriteLine("IB method");
}
public virtual void Hello1(int a, int b)
{
Console.WriteLine("Hello1 method");
}
}
public class ABC : AB,IA,IB
{
void IA.Hello(int a, int b)
{
Console.WriteLine("ABC method");
}
void IB.Hello(int a, int b)
{
Console.WriteLine("ABC method");
}
public override void Hello1(int a, int b)
{
//base.add1(a, b);
Console.WriteLine("Hello1 override method");
}
}

How to call a method from a parent class's base class

Can I call a method from a grandparent class, and if so, how?
I'm trying to do something like this:
class A {
void foo() {
// Do something...
}
}
class B : A {
override void foo() {
// Do something else...
}
}
class C : B {
override void foo() {
// Call A's foo method
// Then do something else
}
}
One approach is to use explicit interface implementation in class A:
This allows you to call A's implementation - both from code within C and from outside C (by casting to IBob first).
using System;
namespace ConsoleApp4
{
interface IBob
{
void foo();
}
class A : IBob
{
void IBob.foo()
{
Console.WriteLine("A");
}
public virtual void foo()
{
((IBob)this).foo();
}
}
class B : A
{
public override void foo()
{
Console.WriteLine("B");
}
}
class C : B
{
public override void foo()
{
Console.WriteLine("C");
// Writes B
base.foo();
// Writes A
((IBob)this).foo();
}
}
public class Program
{
static void Main(string[] args)
{
var sally = new C();
sally.foo(); // A B C
IBob sally2 = sally;
sally2.foo(); // A
Console.ReadLine();
}
}
}

Method overloading and polymorphism

class Program
{
static void Main(string[] args)
{
List<A> myList = new List<A> {new A(), new B(), new C()};
foreach (var a in myList)
{
Render(a);
}
Console.ReadKey();
}
private static void Render(A o)
{
Console.Write("A");
}
private static void Render(B b)
{
Console.Write("B");
}
private static void Render(C c)
{
Console.Write("C");
}
}
class A
{
}
class B : A
{
}
class C : A
{
}
The output is: AAA
Is it possible to somehow use method overloading, so that the output would be: ABC?
You can use dynamic typing if you're using C# 4:
foreach (dynamic a in myList)
{
Render(a);
}
Within static typing, overload resolution is performed at compile-time, not at execution time.
For the implementation to be chosen at decision time, you either have to use overriding instead of overloading, or use dynamic typing as above.
The following ought to do the trick, where we control the behaviour when working with a type within that type:
class A
{
public virtual void Render()
{
Console.WriteLine("A");
}
}
class B : A
{
public override void Render()
{
Console.WriteLine("B");
}
}
class C : A
{
public override void Render()
{
Console.WriteLine("C");
}
}
static void Main(string[] args)
{
var myList = new List<A> { new A(), new B(), new C() };
foreach (var a in myList)
{
a.Render();
}
Console.ReadKey();
}
And if you want the defined behaviour of a type to be additive to that of its parent, then call the method implemented in the base after executing your own logic, for example:
class B : A
{
public override void Render()
{
Console.WriteLine("B");
base.Render();
}
}
Another way to accomplish this is with the visitor pattern: it allows you to achieve something like polymorphism using a two-way method calling system:
interface IRenderable
{
AcceptForRender(Program renderer);
}
class Program
{
static void Main(string[] args)
{
var p = new Program();
var myList = new List<IRenderable> {new A(), new B(), new C()};
foreach (var a in myList)
{
a.AcceptForRender(p);
}
Console.ReadKey();
}
public void Render(A o)
{
Console.Write("A");
}
public void Render(B b)
{
Console.Write("B");
}
public void Render(C c)
{
Console.Write("C");
}
}
class A : IRenderable
{
public void AcceptForRender(Program renderer)
{
renderer.Render(this);
}
}
class B : IRenderable
{
public void AcceptForRender(Program renderer)
{
renderer.Render(this);
}
}
class C : IRenderable
{
public void AcceptForRender(Program renderer)
{
renderer.Render(this);
}
}
The advantage to this approach is that it allows you to effectively achieve polymorphism (each type ensures the correct overload is called by passing the strongly-typed this to Render internally) while keeping logic that does not belong in your types themselves (e.g., visual rendering logic) out.
Make A B C deriving from a base ( abstract ) class, define in that class a method Render and override properly in each A B C . Instead of calling Render(a) then call a.Render() this is the way polymorfism is supposed to work.

Method having an abstract class as a parameter

I have an abstract class A, where I have derived the classes B and C.
Class A provides an abstract method DoJOB(), which is implemented by both derived classes.
There is a class X which has methods inside, which need to call DoJOB().
The class X may not contain any code like B.DoJOB() or C.DoJOB().
Example:
public class X
{
private A foo;
public X(A concrete)
{
foo = concrete;
}
public FunnyMethod()
{
foo.DoJOB();
}
}
While instantiating class X I want to decide which derived class (B or C) must be used.
I thought about passing an instance of B or C using the constructor of X.
X kewl = new X(new C());
kewl.FunnyMethod(); //calls C.DoJOB()
kewl = new X(new B());
kewl.FunnyMethod(); // calls B.DoJOB()
My test showed that declaring a method with a parameter A is not working. Am I missing something?
How can I implement this correctly?
(A is abstract, it cannot be instantiated)
EDIT:
Sorry, I forgot sth.
class A is a generic abstract singleton:
abstract public class A<T> where T : A<T>
{
....
}
public sealed class B : A<B>
{
.....
}
public sealed class C : A<C>
{
.....
}
See the example:
http://www.c-sharpcorner.com/UploadFile/snorrebaard/GenericSingleton11172008110419AM/GenericSingleton.aspx
Under the head line "The solution with the Generic Singleton as an abstract class"
You must have made a mistake in the test, the code works fine:
void Main()
{
X kewl = new X(new C());
kewl.FunnyMethod(); //calls C.DoJOB()
kewl = new X(new B());
kewl.FunnyMethod(); // calls B.DoJOB()
}
public class X
{
private A foo;
public X(A concrete)
{
foo = concrete;
}
public void FunnyMethod()
{
foo.DoJOB();
}
}
public abstract class A
{
public abstract void DoJOB();
}
public class B : A
{
public override void DoJOB()
{
Console.WriteLine("B");
}
}
public class C : A
{
public override void DoJOB()
{
Console.WriteLine("C");
}
}
Outputs :
C
B
For your edit:
void Main()
{
var kewl = new X<C>(new C());
kewl.FunnyMethod(); //calls C.DoJOB()
var kewl2 = new X<B>(new B());
kewl2.FunnyMethod(); // calls B.DoJOB()
}
public class X <T> where T : A<T>
{
private A<T> foo;
public X(A<T> concrete)
{
foo = concrete;
}
public void FunnyMethod()
{
foo.DoJOB();
}
}
public abstract class A<T> where T : A<T>
{
public abstract void DoJOB();
}
public class B : A<B>
{
public override void DoJOB()
{
Console.WriteLine("B");
}
}
public class C : A<C>
{
public override void DoJOB()
{
Console.WriteLine("C");
}
}
Works for me. I get the expected
I did something interesting!
So Did I!
when I run it.
Paste this in your Visual Studio and smoke it
using System;
namespace TestDrive
{
class Program
{
static void Main( string[] args )
{
ServiceConsumer x = new ServiceConsumer( new ConcreteService2() ) ;
x.FunnyMethod() ;
return ;
}
}
abstract class AbstractService
{
public abstract void DoSomethingInteresting() ;
}
class ConcreteService1 : AbstractService
{
public override void DoSomethingInteresting()
{
Console.WriteLine("I did something interesting!");
return ;
}
}
class ConcreteService2 : ConcreteService1
{
public override void DoSomethingInteresting()
{
base.DoSomethingInteresting() ;
Console.WriteLine("So Did I!");
return ;
}
}
class ConcreteService : AbstractService
{
public override void DoSomethingInteresting()
{
Console.WriteLine("Not It's my turn to do something interesting!") ;
return ;
}
}
class ServiceConsumer
{
private AbstractService Service ;
public ServiceConsumer( AbstractService serviceInstance )
{
this.Service = serviceInstance ;
return ;
}
public void FunnyMethod()
{
Service.DoSomethingInteresting() ;
return ;
}
}
}
Cheers!
I'm not sure I understand the question, here is my implementation and it works:
namespace CSharpConsole {
public abstract class A {
public abstract void Test();
}
public class B : A {
public override void Test() {
System.Console.WriteLine("B:Test called!");
}
}
public class C : A {
public override void Test() {
System.Console.WriteLine("C:Test called!");
}
}
class Program {
private A _concrete;
public Program(A concrete) {
_concrete = concrete;
}
public void DoTest() {
_concrete.Test();
}
static void Main(string[] args) {
Program pb = new Program(new B());
pb.DoTest();
Program pc = new Program(new C());
pc.DoTest();
}
}
}

Categories

Resources