The code is simple enough to understand I hope.
I'm trying to use an interface type IColor in order to pass color objects to the ColorManager. I then want the ColorManager to pass this object to the IColor object as its own type, so the method overloads gets called.
However, it seems since it is being passed as the IColor type, C# will not implicity cast it into its complete type as either a BlueColor or GreenColor.
I hope this makes some sense to somebody on what I want to achieve. Is this possible in C#?
[Solution]
http://msdn.microsoft.com/en-us/library/dd264736.aspx
Overload Resolution with Arguments of Type dynamic
My code so far:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
namespace Example
{
public interface IColor
{
void CatchColor(IColor c);
}
public class BlueColor : IColor
{
public void CatchColor(IColor c)
{
}
}
public class GreenColor : IColor
{
public void CatchColor(BlueColor c)
{
Console.WriteLine("CAUGHT BLUE!");
}
public void CatchColor(GreenColor c)
{
Console.WriteLine("CAUGHT GREEN!");
}
public void CatchColor(IColor c)
{
Console.WriteLine("CAUGHT SOME COLOR!");
}
}
public class ColorManager
{
public void PassColor(IColor c)
{
// Don't use static type-checking
// Problem solved
dynamic AnyColor = c;
AnyColor.CatchColor(AnyColor);
}
public static void Main()
{
GreenColor G = new GreenColor();
new ColorManager().PassColor(G);
Console.ReadLine();
return;
}
}
}
One possiblity to tell the ColorManager class to use the correct type of the passed object is to use an abstract class, that already implements the CatchColor:
public abstract class IColor
{
// override in every class
public abstract void PrintColor();
// has the correct type passed with the interface
public void CatchColor(IColor c)
{
c.PrintColor();
}
}
Then the sub classes need to implement only PrintColor with the correct color:
public class BlueColor : IColor
{
public override void PrintColor()
{
Console.WriteLine("BLUE!");
}
}
public class GreenColor : IColor
{
public override void PrintColor()
{
Console.WriteLine("GREEN!");
}
}
The manager is the same:
public class ColorManager
{
public void PassColor(IColor c)
{
c.CatchColor(c);
}
}
It can be used like this:
GreenColor G = new GreenColor();
var cm = new ColorManager();
cm.PassColor(G);
cm.PassColor(new BlueColor());
The outputs is:
GREEN!
BLUE!
What you want is late method binding.
The downside to this is you have to add methods for each new type of color. The upside is you don't have to maintain a case statement or conditional logic.
See here for more detail:
Early and late binding
Edit: Here is a working example of this type of late-binding.
class Program {
static void Main(string[] args) {
//Declare instances
BaseClass myClass = new Class2();
BaseClass otherClass = new Class1();
//Invoke the action method which will match based on the BaseClass type
Action(myClass);
Action(otherClass);
Console.ReadLine();
}
public static void Action(BaseClass classType) {
//Remove the compile-time type so the runtime can select the method based on signature
dynamic aClass = classType;
ServiceMethod(aClass);
}
public static void ServiceMethod(dynamic input) {
Methods(input);
}
public static void Methods(Class1 classType) {
Console.WriteLine("Class1");
Debug.WriteLine("Class1");
}
public static void Methods(Class2 classtype) {
Console.WriteLine("Class2");
Debug.WriteLine("Class2");
}
public static void Methods(Class3 classType) {
Console.WriteLine("Class3");
Debug.WriteLine("Class3");
}
}
public abstract class BaseClass { //This could also be an interface
public Guid Id { get; set; }
public string Name { get; set; }
}
public class Class1 : BaseClass {
}
public class Class2 : BaseClass{
}
public class Class3 : BaseClass {
}
So you want something like:
public void CatchColor(Color c)
{
if (c is BlueColor)
CatchColor(c as BlueColor);
if (c is GreenColor)
CatchColor(c as GreenColor);
}
?
Related
Is it possible to use a subset of methods as member methods in different classes in C#?
For instance, I have four functions the void A(), the void B(), the void C() and the void D().
And now I want to have three classes. The first class I would like to have the member methods A, B and C. The second I would like to have the B and D. And the third the A, C and D.
How could I achieve this? Is it possible to achieve this only by using interfaces or are there any other approaches?
If all your three classes should have different implementations for these methods, then classic interfaces are the way to go:
public interface IHaveA {
void A();
}
public interface IHaveB {
void B();
}
public interface IHaveC {
void C();
}
public interface IHaveD {
void D();
}
public class Class1 : IHaveA, IHaveB, IHaveC { // Implement A, B and C here }
public class Class2 : IHaveB, IHaveD { // Implement B and D here }
public class Class3 : IHaveA, IHaveC, IHaveD { // Implement A, C and D here }
If all your classes should have the same implementation of A, B, C and D, you could still use interfaces but you would have to duplicate code:
public static class StaticImplementation {
public void A(IHaveA sender) {
// Do stuff here
}
public void B(IHaveB sender) {
// Do stuff here
}
public void C(IHaveC sender) {
// Do stuff here
}
public void D(IHaveD sender) {
// Do stuff here
}
}
public class Class1 : IHaveA, IHaveB, IHaveC {
public void A() { StaticImplementation.A(this) }
public void B() { StaticImplementation.B(this) }
public void C() { StaticImplementation.C(this) }
}
public class Class2 : IHaveB, IHaveD { // Calls to StaticImplementation for B and D here }
public class Class3 : IHaveA, IHaveC, IHaveD { // Calls to StaticImplementation for A, C and D here }
There is no way to enforce that these three classes have the same implementation of these methods using interfaces, because the primary goal interfaces is to ensure that classes implement methods, specifically with different implementations!
This changes in C# 8.0 and .NET Core 3.0 where you can have default implementations for interface methods, and you could ensure that these implementations do not change by sealing them.
The code would become:
public interface IHaveA {
sealed void A() {
// Implementation here
}
}
public interface IHaveB {
sealed void B() {
// Implementation here
}
}
public interface IHaveC {
sealed void C() {
// Implementation here
}
}
public interface IHaveD {
sealed void D() {
// Implementation here
}
}
public class Class1 : IHaveA, IHaveB, IHaveC { // Nothing to do here }
public class Class2 : IHaveB, IHaveD { // Nothing to do here }
public class Class3 : IHaveA, IHaveC, IHaveD { // Nothing to do here }
using System;
public interface MA {}
public static class MAProvider {
public static void A(this MA obj) { Console.WriteLine("MA"); }
}
public interface MB {}
public static class MBProvider {
public static void B(this MB obj) { Console.WriteLine("MB"); }
}
public interface MC {}
public static class MCProvider {
public static void C(this MC obj) { Console.WriteLine("MC"); }
}
public interface MD {}
public static class MDProvider {
public static void D(this MD obj) { Console.WriteLine("MD"); }
}
public class First : MA, MB, MC {}
public class Second : MB, MD {}
public class Third : MA, MC, MD {}
public static class Program {
public static void Main() {
new First().A();
new First().B();
new First().C();
new Second().B();
new Second().D();
new Third().A();
new Third().C();
new Third().D();
}
}
The only issue which is left is the private members. Since we can not access them inside the extension methods.
I have Generator class that generates objects with different Interfaces with different probabilities. All objects generated by Generator is of type BaseClass. BaseClass is an abstract base class.
Lets say interfaces are I1, I2
I have another class Resolver that has polymorphic method for two interfaces as follows:
Resolve(I1 myObj){//code for I1}
Resolve(I2 myObj){//code for I2}
The main class looks like this:
BaseClass event = Generator.generate(); //event is implements I1 or I2. Not known what interfaces until run time.
Resolver.Resolve(event); //Here i got an error, because event is BaseClass type and not I1 or I2 type.
Is there a way to solve this issue without explicitly check Interface type and cast it to appropriate interface. I came from python background, so statically typed language is new for me.
Consider using dependency injection to allow the event object to call the Resolver itself.
public interface IResolvable
{
void Resolve(Resolver resolver);
}
public interface I1 : IResolvable { //... }
public interface I2 : IResolvable { //... }
public class Resolver
{
public void Resolve(I1 i) { //... }
public void Resolve(I2 i) { //... }
}
public abstract class BaseClass : IResolvable
{
public abstract void Resolve(Resolver resolver);
//...
}
An implementation would look something like:
public class Implementation1 : BaseClass, I1
{
public override void Resolver(Resolver resolver)
{
resolver.Resolve(this);
}
//...
}
And then calling it:
Resolver resolver = new Resolver();
IResolvable evnt = Generator.Generate();
evnt.Resolve(resolver);
We can go a step further and make an interface for Resolver, so we can mock it for unit testing purposes and take full advantage of the DI pattern.
public interface IResolver
{
void Resolve(I1 i) { //... }
void Resolve(I2 i) { //... }
}
Then we change the definition of IResolvable
public interface IResolvable
{
void Resolve(IResolver resolver);
}
Here is some code that demonstrates virtual function approach that doesn't need casting.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
interface IBase
{
void Function();
}
class BaseClass : IBase
{
public virtual void Function()
{
}
}
interface I1: IBase
{
}
interface I2 : IBase
{
}
class C1: BaseClass, I1
{
public override void Function()
{
Console.WriteLine("Hello from C1");
}
}
class C2 : BaseClass, I1
{
public override void Function()
{
Console.WriteLine("Hello from C2 !!!");
}
}
static class Generator
{
public static BaseClass generateC1()
{
return new C1();
}
public static BaseClass generateC2()
{
return new C2();
}
}
class Program
{
static void Main(string[] args)
{
BaseClass b1 = Generator.generateC1();
b1.Function();
Console.WriteLine("-------");
BaseClass b2 = Generator.generateC2();
b2.Function();
Console.WriteLine("End!");
}
}
}
EDIT I adjusted my answer because I did not understand the question correctly the first time.
I think that you can not achieve exactly what you would like to without using casts. As far as I understand as soon as you reference the object you get from Generator.generate() by its base type it is not possible to access the object by its specialized type again without casting it.
I can think of two alternatives which might be interesting for you. One is using C# 7 pattern matching (which is a bit like using casts) and the other is using dynamic.
Pattern matching
using System;
namespace EventREsolver
{
public interface IEvent { }
public class Event1 : IEvent { }
public class Event2 : IEvent { }
public class Resolver
{
public void Resolve(IEvent theEvent)
{
switch (theEvent)
{
case Event1 e1: Resolve(e1); break;
case Event2 e2: Resolve(e2); break;
default: throw new ArgumentException("not a recognized type", nameof(theEvent));
}
}
private void Resolve(Event1 theEvent)
{
Console.WriteLine("Resolve I1");
}
private void Resolve(Event2 theEvent)
{
Console.WriteLine("Resolve I2");
}
}
public class Generator
{
int state = 0;
public IEvent Generate()
{
if (state == 0)
{
state++;
return new Event1();
}
return new Event2();
}
}
class Program
{
static void Main(string[] args)
{
var generator = new Generator();
var event1 = generator.Generate();
var event2 = generator.Generate();
var resolver = new Resolver();
resolver.Resolve(event1);
resolver.Resolve(event2);
Console.ReadKey();
}
}
}
Dynamic
using System;
namespace EventREsolver
{
public interface IEvent { }
public class Event1 : IEvent { }
public class Event2 : IEvent { }
public class Resolver
{
public void Resolve(Event1 theEvent)
{
Console.WriteLine("Resolve I1");
}
public void Resolve(Event2 theEvent)
{
Console.WriteLine("Resolve I2");
}
}
public class Generator
{
int state = 0;
public IEvent Generate()
{
if (state == 0)
{
state++;
return new Event1();
}
return new Event2();
}
}
class Program
{
static void Main(string[] args)
{
var generator = new Generator();
dynamic event1 = generator.Generate();
dynamic event2 = generator.Generate();
var resolver = new Resolver();
resolver.Resolve(event1);
resolver.Resolve(event2);
Console.ReadKey();
}
}
}
Hi everyone I am programming in Unity3d with C# and while I was writing my code I stumbled with a little issue, I write to you an example because I dont know explain me.
class Base
{
public string name;
}
class Derived : Base
{
public void Gun();
}
class BasePlayer
{
public Base x;
}
class SoldierPlayer : BasePlayer
{
}
The situation is this, I want to do something like that
SoldierPlayer.x.Gun();
But I don't know how do it
The real case is this
public class BasePlayerController : MonoBehaviour
{
public BasePlayerManager playerManager;
...
public class RobotPlayerController : BasePlayerController {
...
playerManager = gameObject.AddComponent<RobotPlayerManager>();
And I will use new methods
UPDATE 1
I did a example better, I want to do in Base Controller manager.user.energy and be treated as the next type RobotManager.RobotUser.energy
BaseController
BaseManager
BaseUser
class BaseController
{
BaseManager manager;
public virtual void Move(int x,int y)...
}
class BaseManager {
BaseUser user;
public virtual Pause(bool state);
}
class BaseUser {
int life
}
RobotController
RobotManager
RobotUser
class RobotController : BaseController
{
// manager as RobotManager?
public void Ray(int x,int y);
}
class RobotManager : BaseManager
{
// user as RobotUser?
}
class RobotUser : BaseUser
{
int energy;
}
UPDATE 2
I seek to do this
public Run()
{
RobotController rc = new RobotController();
rc.manager.energy;
}
You can't call SoldierPlayer.x.Gun(); because SoldierPlayer.x has type Base which has not method Gun(). OOP world and C# can provide you many solutions, your choose depends on your goals.
some of them (order by best practise):
1) Overriding Polymorphism. Add .Gun() method to Base class and implemend it in derived classes. For example
class Base
{
public string name;
public void virtual Gun()
{
Trace.Log("I'm base class, i can't do anything");
}
}
class Derived : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have gun");
}
}
class Derived2 : Base
{
public override void Gun()
{
Consule.WriteLine("Hello i have 2 guns");
}
}
2) Overloading Polymorphism In many source this method is mentioned like some kind of polymorphism AD-HOC
public void GunAction(Derived2 o)
{
o.Gun();
}
public void GunAction(Derived1 o)
{
o.Gun();
}
public void GunAction(Base o)
{
Trace.Log("I'm base class, i can't do anything");
}
3) is-cast
public void GunAction(Base o)
{
if(o is Derived1 )
o.Gun();
if(o is Derived2 )
o.Gun();
}
UPDATE 1 answering to your new requirements
class BaseController
{
public BaseManager manager;
...
class RobotController1 : BaseController
{
// manager as RobotManager? - no it is stil BaseManager
public void Ray(int x,int y);
}
class RobotController2 : BaseController
{
// manager as RobotManager? - yes. now it is RobotManager
public void Ray(int x,int y);
public RobotController2()
{
manager = new RobotManager();
}
}
public void Run()
{
var controller = new RobotController2();// you have RobotManager
controller.manager = new BaseManager();// it is again BaseManager
}
I have an abstract base class called Rack and I have different types of racks that are the children of Rack. I want to be able to dynamically cast the generic C# object to different children of the Rack class in order to call the correct getData method in which all children have as a method. Here is what I have so far.
The code below calls the virtual method in the Rack base class. I need it to call the methods within the child classes of Rack.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace IO_Interface
{
class Channel
{
private object rack1;
private object rack2;
public Channel()
{
}
public Channel(object h1, object h2)
{
rack1 = h1;
rack2 = h2;
}
public void send()
{
Type rack1Info = rack1.GetType();
Type rack2Info = rack2.GetType();
string name = rack1.ToString();
MethodInfo castMethod = rack1.GetType().GetMethod("getData").;
castMethod.Invoke(rack1.GetType(), null);
}
}
}`
What you want to do is declare your rack1 and rack2 as Racks, which will be an abstract class with an abstract method GetData. You will instantiate them as child classes of Rack somewhere. Then, when you make a call to GetData on a Rack, it will find the overridden method and call it. Here's an example.
abstract class Rack
{
public abstract void GetData();
}
class ChildRack1 : Rack
{
public override void GetData(){}
}
class ChildRack2 : Rack
{
public override void GetData(){}
}
class Channel
{
private Rack rack1;
private Rack rack2;
public Channel()
{
}
public Channel(Rack h1, Rack h2)
{
rack1 = h1;
rack2 = h2;
}
public void send()
{
rack1.GetData();
}
}
I think this will provide you with the implementation you want:
class Channel
{
private List<Rack> racks;
public Channel()
{
racks = new List<Rack>();
}
public Channel(params Rack[] racks)
{
this.racks = racks.ToList();
}
public void send()
{
foreach (Rack item in racks)
{
item.getData();
}
}
public void SendSpecificRack(Rack rack)
{
//calls the getdata of the rack object passed
rack.getData();
}
}
public class Rack
{
public virtual void getData()
{
Console.WriteLine("Base Rack");
}
}
public class RackChild1 : Rack
{
public override void getData()
{
Console.WriteLine("RackChild1");
}
}
public class RackChild2 : Rack
{
public override void getData()
{
Console.WriteLine("RackChild2");
}
}
Usage:
Channel chn = new Channel(new Rack[]{new RackChild1(),new RackChild2()});
chn.send();
RackChild2 rck = new RackChild2();
chn.SendSpecificRack(rck);
Output:
RackChild1
RackChild2
RackChild2
How can I get the type (not a name string, but a type itself) of the current class, in a static method of an abstract class?
using System.Reflection; // I'll need it, right?
public abstract class AbstractClass {
private static void Method() {
// I want to get CurrentClass type here
}
}
public class CurrentClass : AbstractClass {
public void DoStuff() {
Method(); // Here I'm calling it
}
}
This question is very similar to this one:
How to get the current class name at runtime?
However, I want to get this information from inside the static method.
public abstract class AbstractClass
{
protected static void Method<T>() where T : AbstractClass
{
Type t = typeof (T);
}
}
public class CurrentClass : AbstractClass
{
public void DoStuff()
{
Method<CurrentClass>(); // Here I'm calling it
}
}
You can gain access to the derived type from the static method simply by passing the type as a generic type argument to the base class.
I think you will have to either pass it in like the other suggestion or create a stack frame, I believe if you put an entire stack trace together though it can be expensive.
See http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx
if you are calling this static method only from derived classes you can use 'System.Diagnostics.StackTrace' like
abstract class A
{
public abstract string F();
protected static string S()
{
var st = new StackTrace();
// this is what you are asking for
var callingType = st.GetFrame(1).GetMethod().DeclaringType;
return callingType.Name;
}
}
class B : A
{
public override string F()
{
return S(); // returns "B"
}
}
class C : A
{
public override string F()
{
return S(); // returns "C"
}
}
The method can't be static if you're going to call it without passing in a type. You can do this:
public abstract class AbstractClass {
protected void Method() {
var t = GetType(); // it's CurrentClass
}
}
If you also need it to be accessible from a static context, you can add an overload, even a generic overload, e.g.:
public abstract class AbstractClass {
protected static void Method<T>() {
Method(typeof(T));
}
protected static void Method(Type t) {
// put your logic here
}
protected void Method() {
Method(GetType());
}
}