There are 3 classes A,B,C . Classes B and C inherit from A.
Class B and C have a function - func1() ,A doesnt.
I have a list<A> OB where every object in it is eaither B or C.
I want to access func1 by OB[0].Func1().
How can i do this?
Thank you!
You're trying to call method func1 on class A, where A does not define it? You can't. You can make Func1 abstract within A if you want to do that.
abstract class A
{
public abstract Func1();
}
class B : A
{
public override Func1()
{
MessageBox.Show("Hello World");
}
}
class C : A
{
public override Func1()
{
MessageBox.Show("Goodbye World");
}
}
The fact that Func1 is abstract means that you can't instantiate A directly, but you can instantiate B.
var listOfA = new List<A>();
listOfA.Add(new B());
listOfA.Add(new C());
listOfA[0].Func1(); // hello world
listOfA[1].Func1(); // goodbye world
You could make Func1 defined as virtual in A instead of setting it as abstract, but I recommend you do not because this will introduce a reversed Refused Bequest design smell.
Add the method to class A as virtual, and make B and C override it:
public class A
{
public virtual void Foo()
{
}
}
public class B : A
{
public override void Foo()
{
}
}
public class C : A
{
public override void Foo()
{
}
}
If it doesn't make sense put func1() or can't change class A you can create a Interface that has func1() and have just class B and C implement that interface. Then when you need to call func1() cast your objects to that interface using the as operator. When using the as operator no exception is thrown if the cast fails.
public interface MyInterface
{
void func1();
}
public class B : MyInterface
{
public func1() {...}
....
}
public class C : MyInterface
{
public void func1() {...}
....
}
//example of calling func1()
List<A> list = new List<A>(stuff);
foreach(A item in list)
{
MyInterface tmp = item as MyInterface;
if(tmp != null)
{
tmp.func1();
}
}
Abstract factory do the same thing you are looking for
i found this code on CodeProject
this might help you
//Let's define type of bread bases
public enum BreadBase
{
HotIndianMasalaBase,
PunjabiTadkaBase,
ItalianCheeseBase,
VeggieBase,
}
//This is a breadfactory where people visit to get their favorite bread bases
public interface BreadFactory
{
Bread GetBread(BreadBase BreadBase);
}
//The abstract bread
public interface Bread
{
void Bake();
}
//create concrete classes
public class HotIndianMasalaBread :Bread
{
public void Bake()
{
Console.WriteLine ("For you::Hotindian Masala base Bread.");
}
}
public class VeggieBread : Bread
{
public void Bake()
{
Console.WriteLine("For you::Veggie base Bread.");
}
}
public class ItalianCheeseBread : Bread
{
public void Bake()
{
Console.WriteLine("For you::Italian cheese base Bread.");
}
}
public class PunjabiTadkaBaseBread : Bread
{
public void Bake()
{
Console.WriteLine("For you::Punjabi tadka base bread.");
}
}
//Lets create bread factories aka concrete classes
public class AmericanBreadFactory :BreadFactory
{
public Bread GetBread(BreadBase BreadBase)
{
Bread vBread = null;
switch (BreadBase)
{
case BreadBase.VeggieBase:
vBread = new VeggieBread();
break;
case BreadBase.ItalianCheeseBase:
vBread = new ItalianCheeseBread();
break;
}
return vBread;
}
}
public class IndianBreadFactory :BreadFactory
{
public Bread GetBread(BreadBase BreadBase)
{
Bread vBread = null;
switch (BreadBase)
{
case BreadBase.HotIndianMasalaBase:
vBread = new HotIndianMasalaBread();
break;
case BreadBase.PunjabiTadkaBase:
vBread = new PunjabiTadkaBaseBread();
break;
}
return vBread;
}
}
//lets order breads
class Program
{
static void Main(string[] args)
{
//example of abstract factory
AmericanBreadFactory vAmericanBread = new AmericanBreadFactory();
Bread vBread = vAmericanBread.GetBread(BreadBase.VeggieBase);
vBread.Bake();
//lets bak indian punjabi tadka bread
IndianBreadFactory vIndianBreadFactory = new IndianBreadFactory();
Bread vIndianBread = vIndianBreadFactory.GetBread(BreadBase.PunjabiTadkaBase);
vIndianBread.Bake();
}
}
Related
In C# I know there is a way of switching method calls based on the concrete type of an abstract parameter at run time.
So in the example below the entire Wash(Animal) method is not needed and C# will know which Cat/Dog method to call based on the concrete type of Animal at run time. There's syntax to do this, I've done this before but I can't for the life of me remember what it is.
public void Wash(Animal animal)
{
switch (animal)
{
case Cat cat:
Wash(cat);
break;
case Dog dog:
Wash(dog);
break;
}
}
public void Wash(Cat cat)
{
}
public void Wash(Dog dog)
{
}
Could be done using double dispatch...
abstract class Animal
{
public abstract void TakeBath(AnimalWasher washer);
}
class Cat : Animal
{
public override void TakeBath(AnimalWasher washer)
{
washer.Wash(this);
}
}
class Dog : Animal
{
public override void TakeBath(AnimalWasher washer)
{
washer.Wash(this);
}
}
class AnimalWasher
{
public void Wash(Cat cat)
{
Console.WriteLine("washing a cat");
}
public void Wash(Dog dog)
{
Console.WriteLine("washing a dog");
}
}
class Program
{
static async Task Main(string[] args)
{
AnimalWasher washer = new AnimalWasher();
Animal dog = new Dog();
Animal cat = new Cat();
dog.TakeBath(washer);
cat.TakeBath(washer);
}
Thank you Mr Skeet for scratching my itch. Dynamic binding is exactly what I was trying to remember.
public void PetGroom(Animal animal)
{
Wash(animal as dynamic);
}
public void Wash(Cat cat)
{
}
public void Wash(Dog dog)
{
}
Suppose I have two implementations of a base class:
public class Base {
public string Stringify() { return "I am a member of base class"; }
}
public class A : Base {
public void DoAThing() {...};
}
public class B : Base {
public void DoBThing(int anInteger) {...};
}
Suppose I want to put many instances of Base in a list, so that I can loop over them and call Stringify() on each, and make use of their shared functionality.
static void Main(string[] args)
{
A thing1 = new A();
B thing2 = new B();
B thing3 = new B();
List<Base> list = new List<Base> {thing1, thing2, thing3};
foreach(Base base in list) { Console.WriteLine(base.Stringify()); }
}
Now suppose there are many many Base objects, such that maintaining the individual thing references to each one is not realistic. Would there be any way, via only the list, to regain the DoAThing() or DoBThing() functionality that is lost by the abstraction without having to use explicit downcasting and reflection?
This feels like it would be a common enough occurance, so I am wondering if there is a design flaw or established pattern I am missing here that would help in this situation.
If you debug, you can notice every object of the list mantains its' class.
This way:
class Program
{
static void Main(string[] args)
{
A thing1 = new A();
B thing2 = new B();
B thing3 = new B();
List<Base> list = new List<Base> { thing1, thing2, thing3 };
foreach (Base bas in list) {
Console.WriteLine(bas.Stringify());
if(bas is A)
{
((A)bas).DoAThing();
}
else if (bas is B)
{
((B)bas).DoBThing(1);
}
else
{
//IDK
}
}
}
}
public abstract class Base
{
public string Stringify() { return "I am a member of base class"; }
}
public class A : Base
{
public void DoAThing()
{
}
}
public class B : Base
{
public void DoBThing(int anInteger)
{
}
}
If we have a class that inherits from multiple interfaces, and the interfaces have methods with the same name, how can we implement these methods in my class? How can we specify which method of which interface is implemented?
By implementing the interface explicitly, like this:
public interface ITest {
void Test();
}
public interface ITest2 {
void Test();
}
public class Dual : ITest, ITest2
{
void ITest.Test() {
Console.WriteLine("ITest.Test");
}
void ITest2.Test() {
Console.WriteLine("ITest2.Test");
}
}
When using explicit interface implementations, the functions are not public on the class. Therefore in order to access these functions, you have to first cast the object to the interface type, or assign it to a variable declared of the interface type.
var dual = new Dual();
// Call the ITest.Test() function by first assigning to an explicitly typed variable
ITest test = dual;
test.Test();
// Call the ITest2.Test() function by using a type cast.
((ITest2)dual).Test();
You must use explicit interface implementation
You can implement one or both of those interfaces explicitly.
Say that you have these interfaces:
public interface IFoo1
{
void DoStuff();
}
public interface IFoo2
{
void DoStuff();
}
You can implement both like this:
public class Foo : IFoo1, IFoo2
{
void IFoo1.DoStuff() { }
void IFoo2.DoStuff() { }
}
You can implement one interface Explicitly and another implecitely.
public interface ITest {
void Test();
}
public interface ITest2 {
void Test();
}
public class Dual : ITest, ITest2
{
public void Test() {
Console.WriteLine("ITest.Test");
}
void ITest2.Test() {
Console.WriteLine("ITest2.Test");
}
}
ITest.Test will be the default implementation.
Dual dual = new Dual();
dual.Test();
((ITest2)dual).Test();
Output:
Console.WriteLine("ITest.Test");
Console.WriteLine("ITest2.Test");
Sometimes you may even need to do:
public class Foo : IFoo1, IFoo2
{
public void IFoo1.DoStuff() { }
public void IFoo2.DoStuff()
{
((IFoo1)this).DoStuff();
}
}
public class ImplementingClass : AClass1, IClass1, IClass2
{
public override string Method()
{
return "AClass1";
}
string IClass1.Method()
{
return "IClass1";
}
string IClass2.Method()
{
return "IClass2";
}
}
So when calling from different class you will have to type cast the object into required Interface or Abstract class.
ImplementingClass implementingClass = new ImplementingClass();
((AClass1)implementingClass).Method();
public interface IDemo1
{
void Test();
}
public interface IDemo2
{
void Test();
}
public class clsDerived:IDemo1,IDemo2
{
void IDemo1.Test()
{
Console.WriteLine("IDemo1 Test is fine");
}
void IDemo2.Test()
{
Console.WriteLine("IDemo2 Test is fine");
}
}
public void get_methodes()
{
IDemo1 obj1 = new clsDerived();
IDemo2 obj2 = new clsDerived();
obj1.Test();//Methode of 1st Interface
obj2.Test();//Methode of 2st Interface
}
Answer is "By using explicit Interface implementation"
Take one example:
using System;
interface A
{
void Hello();
}
interface B
{
void Hello();
}
class Test : A, B
{
void A.Hello()
{
Console.WriteLine("Hello to all-A");
}
void B.Hello()
{
Console.WriteLine("Hello to all-B");
}
}
public class interfacetest
{
public static void Main()
{
A Obj1 = new Test();
Obj1.Hello();
B Obj2 = new Test();
Obj2.Hello();
}
}
Output:
Hello to all-A
Hello to all-B
Dual dual = new Dual();
(dual as ITest).Test();
(dual as ITest2).Test();
you can use that for your code
I have these structure
class A : IFoo {
Foo(){
//do something
}
IList<B> Bs {get;set;}
IList<C> Cs {get;set;}
}
class B : IFoo {
Foo(){
//do something
}
IList<D> Ds {get;set;}
}
class C : IFoo {
Foo(){
//do something
}
}
class D : IFoo {
Foo(){
//do something
}
}
class Helper{
Bar(A a){
a.Foo();
Bar(a.Bs);
Bar(a.Cs);
}
Bar(IList<B> bs)
{
foreach(var b in bs)
{
Bar(b);
}
}
Bar(B b)
{
b.Foo();
Bar(b.Ds);
}
Bar(IList<C> cs)
{
foreach(var c in cs)
{
Bar(c);
}
}
Bar(C c)
{
c.Foo();
}
Bar(IList<D> ds)
{
foreach(var d in ds)
{
Bar(d);
}
}
Bar(D d)
{
d.Foo();
}
}
interface IFoo {
void Foo();
}
As you see a lot of code is repeated in Helper class (i.e. method Bar) for different types of A,B,C,IList<A>,IList<B>,IList<C>. Also when a new list property is added to the classes I need to get back and change the Helper class which is somehow in contradiction with Open/Close principal.
I know how to use Reflection to solve the issue, but I was searching for another smart and neat way to solve this issue and not using Reflection.
I am free to add new Interfaces but not base class
Any suggestion will be appreciated
If you want to keep the OPEN/CLOSE principle intact, you can go with something like this -
Each class will extend as necessary.
New class does not need to modify old class- Helper. So the implementation becomes somewhat like the one below. NO matter how many class you add, each class is responsible for there own Foo and Bar implementation.
Example -
public interface IFoo
{
void Foo();
void Bar();
}
public abstract class BaseFoo : IFoo
{
public virtual void Foo()
{
//do nothing
}
public virtual void Bar()
{
//do nothing
}
}
public class A : BaseFoo //replace with IFoo if you do not want the base class, in that case implement both methods
{
IList<B> Bs { get; set; }
IList<C> Cs { get; set; }
public override void Bar()
{
base.Bar();
foreach (var b in Bs)
{
b.Bar();
}
foreach (var c in Cs)
{
c.Bar();
}
}
}
public class B : BaseFoo //replace with IFoo if you do not want the base class, in that case implement both methods
{
IList<D> Ds { get; set; }
public override void Bar()
{
base.Bar();
foreach (var d in Ds)
{
d.Bar();
}
}
}
public class C : BaseFoo //replace with IFoo if you do not want the base class, in that case implement both methods
{
}
public class D : BaseFoo //replace with IFoo if you do not want the base class, in that case implement both methods
{
}
public static class Helper
{
public static void Bar(params IFoo[] foos)
{
foreach (var foo in foos)
{
foo.Bar();
}
}
}
Assuming that method Foo() exists on the IFoo interface, and given that your Bar methods for B, C and D do nothing other than invoke the Foo implementation for the class, why not remove the Bar overloads altogether (since the dependency coupling is only to the interface method Foo())
Your looped method becomes (renamed from Bar(IList<B/C/D> bs)):
void InvokeFoo(IEnumerable<IFoo> foos)
{
foreach(var foo in foos)
{
foo.Foo();
}
}
Which would be invoked:
Bar(A a){
a.Foo();
InvokeFoo(a.Bs);
InvokeFoo(a.Cs);
}
Edit
The above answer misses the fact that classes (e.g. B) can have child collections, through which you also need to iterate. If these child collections are arbitrary in number (e.g. A has 2 such collections, B has 1, and C and D none), and given your statement that you can't modify the actual classes A, B, C etc, you could specify a 'special' action to be taken for each class. This would be a naive implementation, which only will work for one level of recursion (which is what you have):
class Helper
{
public void Bar(A a)
{
a.Foo();
InvokeFoo(a.Bs, foo => InvokeFoo(((B)foo).Ds));
InvokeFoo(a.Cs);
}
void InvokeFoo(IEnumerable<IFoo> foos, Action<IFoo> childAction = null)
{
foreach (var foo in foos)
{
foo.Foo();
childAction?.Invoke(foo);
}
}
}
Making this more generic / Recursive
Since it seems you aren't allowed to modify the classes (only the helper), violation of the Open+Closed principal of SOLID seems inevitable (since the navigation is done by an external observer).
As a poor man's form of polymorphicism, and to keep the 'smell' in one place, what you could do is provide an overload to assist each type walk it's children. The default behaviour (as per my first code) is simply to invoke Foo, if no type is found:
class Helper
{
private static readonly IDictionary<Type, Action<IFoo>> SpecialClassActions
= new Dictionary<Type, Action<IFoo>>
{
// Provide special handling for walking classes which have children
{
typeof(A),
foo =>
{
InvokeChildFoo(((A)foo).Bs);
InvokeChildFoo(((A)foo).Cs);
}
},
{
typeof(B),
foo =>
{
InvokeChildFoo(((B)foo).Ds);
}
}
// Add more handling here as new subtypes are added
};
static void WalkFooHierarchy(IFoo foo)
{
foo.Foo();
Action<IFoo> specialChildAction;
if (SpecialClassActions.TryGetValue(foo.GetType(), out specialAction))
{
specialChildAction(foo);
}
}
// Replaces your Bar(IList<> ..) methods
static void InvokeChildFoo(IEnumerable<IFoo> foos)
{
foreach (var foo in foos)
{
WalkFooHierarchy(foo);
}
}
You then kick the process off by starting to walk from your root level object:
public void Bar(A a)
{
Helper.WalkFooHierarchy(a);
}
Based on priceless suggestions and solutions I ended up like below, this solution is Open/Closed and by adding another list only that class should be changed and all of the overloads of Bar in Helper class is removed.
class Program
{
static void Main(string[] args)
{
Helper.Bar(new A());
}
}
public class A : IFoo, IMap
{
public A()
{
Cs = new List<C> { new C(), new C() };
Bs = new List<B> { new B(), new B() };
}
public void Foo()
{
Console.WriteLine("A");
}
public List<B> Bs { get; set; }
public List<C> Cs { get; set; }
public List<Func<dynamic, List<IFoo>>> Map()
{
return this.CreateMap()
.Then(x => ((List<B>)x.Bs).ToList<IFoo>())
.Then(x => ((List<C>)x.Cs).ToList<IFoo>());
}
}
public class B : IFoo, IMap
{
public B()
{
Ds = new List<D> { new D(), new D() };
}
public void Foo()
{
Console.WriteLine("B");
}
public List<Func<dynamic, List<IFoo>>> Map()
{
return this.CreateMap()
.Then(x => ((List<D>)x.Ds).ToList<IFoo>());
}
public List<D> Ds { get; set; }
}
public class C : IFoo, IMap
{
public void Foo()
{
Console.WriteLine("C");
}
public List<Func<dynamic, List<IFoo>>> Map()
{
return this.CreateMap();
}
}
public class D : IFoo, IMap
{
public void Foo()
{
Console.WriteLine("D");
}
public List<Func<dynamic, List<IFoo>>> Map()
{
return this.CreateMap();
}
}
public static class Mapper
{
public static List<Func<dynamic, List<IFoo>>> CreateMap(this IFoo item)
{
return new List<Func<dynamic, List<IFoo>>>();
}
public static List<Func<dynamic, List<IFoo>>> Then(this List<Func<dynamic, List<IFoo>>> list, Func<dynamic, List<IFoo>> expression)
{
list.Add(expression);
return list;
}
}
public class Helper
{
public static void Bar(dynamic obj)
{
obj.Foo();
var map = obj.Map();
if (map != null)
{
foreach(var item in map)
{
var lists = item(obj);
foreach(var list in lists)
{
Bar(list);
}
}
}
}
}
public interface IFoo
{
void Foo();
}
public interface IMap
{
List<Func<dynamic, List<IFoo>>> Map();
}
#brainlesscoder, #StuartLC : since your solutions are also correct I only up-vote them and I don't tag any of the solutions as answer to keep this thread open and might someone else suggests a better solution than us. If you think my solution is also good please up-vote ;)
This seems to me to be the most straight-forward way to do this:
public static class Helper
{
public static void Bar<F>(F f) where F : IFoo
{
f.Foo();
Helper.Bar((f as A)?.Bs);
Helper.Bar((f as A)?.Cs);
Helper.Bar((f as B)?.Ds);
}
public static void Bar<F>(IList<F> fs) where F : IFoo
{
if (fs != null)
{
foreach (var f in fs)
{
Helper.Bar(f);
}
}
}
}
Now if the rest of the code is defined like this:
public class A : IFoo
{
public void Foo() { Console.Write("A"); }
public IList<B> Bs { get; set; } = new List<B>() { new B(), new B(), };
public IList<C> Cs { get; set; } = new List<C>() { new C(), new C(), };
}
public class B : IFoo
{
public void Foo() { Console.Write("B"); }
public IList<D> Ds { get; set; } = new List<D>() { new D(), new D(), };
}
public class C : IFoo
{
public void Foo() { Console.Write("C"); }
}
public class D : IFoo
{
public void Foo() { Console.Write("D"); }
}
public interface IFoo
{
void Foo();
}
...then you can run this:
var a = new A();
var b = new B();
var c = new C();
var d = new D();
Helper.Bar(a);
Helper.Bar(b);
Helper.Bar(c);
Helper.Bar(d);
...and you get ABDDBDDCCBDDCD as expected as the output.
Code to demonstrate the problem:
static void Main(string[] args)
{
var a = new A();
var b = new B();
Base<>[] all = new Base<>[] { a, b }; // doesn't work
}
class Base<T>
{
public string Caption { get { return typeof(T).ToString(); } }
}
class A : Base<A> { }
class B : Base<B> { }
Perhaps I went the wrong direction. Idea was to move Caption into base class (Base become generic). Non-generic version works without problems:
var all = new Base[] { a, b }; // no problems for as long as Base is not generic
There's no Type<?> in C# - you always have to specify a concrete generic type.
The only way around this is to make Base<T> inherit a non-generic base-class, or implement a non-generic interface. You could then use that as the type of the array.
EDIT:
In your case this is extremely simple, since the part of the interface you want doesn't include the generic type argument. So you can simply do either:
public abstract class Superbase
{
public abstract string Caption { get; }
}
public class Base<T>: Superbase
{
public override string Caption { get { return typeof(T).Name; } }
}
Or, using an interface:
public interface IBase
{
string Caption { get; }
}
public class Base<T>: IBase
{
public string Caption { get { return typeof(T).Name; } }
}
Your array would then be Superbase[] or IBase[], respectivelly. In both cases, you can see that I'm not actually providing an implementation - both the declarations are "abstract", in a sense.
In general, I'm trying to keep the non-generic stuff in a non-generic base class, rather than stuffing it in the derived generic classes. It just feels more clean :)
based on #Luaan ideea, here is an implementation:
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
var arr = new Base[] { a, b};
foreach (var obj in arr)
Console.WriteLine(obj.Caption);
Console.ReadKey();
}
}
public class Base<T> : Base
{
public override string Caption
{
get { return typeof (T).ToString(); }
}
}
public class A : Base<A> { }
public class B : Base<B> { }
public abstract class Base
{
public abstract string Caption { get; }
}
Instead of trying to use inheritance (which will lead to more problems down the line), use an extension method instead:
public interface IClassAORClassB {}
class A : IClassAORClassB { }
class B : IClassAORClassB { }
public static class Captions
{
public static string Caption<T>(this T obj) where T : IClassAORClassB
{
return obj.GetType().ToString();
}
}
static void Main(string[] args)
{
var a = new A();
var b = new B();
var all = new IClassAORClassB[] { a, b }; // works just fine
Console.WriteLine(all[0].Caption()); // prints A
Console.WriteLine(all[1].Caption()); // prints B
}