The follow code does not compile:
public class Test
{
public void Run()
{
List<MyClass<dynamic>> listOfMyClasses = new List<MyClass<dynamic>>();
MyClass<dynamic> myClass = new MyClass<int>(); // Error here
listOfMyClasses.Add(myClass);
}
public class MyClass<T>
{
public void DoSomething() { }
public void DoSomethingSpecial<T>(T t) { }
}
}
However, I believe it makes sense logically (please let me know if I'm mistaken). Presumably it is useful, for I can call DoSomething without knowing the type parameter. How can I accomplish the addition of myClass to the list?
Instead of using a list of MyClass<dynamic> just use a List of dynamic:
public void Run()
{
List<dynamic> listOfMyClasses = new List<dynamic>();
dynamic myClass = new MyClass<int>();
listOfMyClasses.Add(myClass);
}
public class MyClass<T>
{
public void DoSomething() { }
}
Related
I wish to cast an object into a generic delegate with system.type information so that I can invoke the delegate. The object is guaranteed to be convertible to the delegate.
Delegate example:
public delegate void CallbackFn<T>(InterfacedDataType<T> data) where T : InterfaceBase;
And the struct holding the callback object and type information:
public struct CallbackFnWrapper
{
public System.Type T;
public object delegateObject;
public void Invoke(InterfaceBase data)
{
((CallbackFn<T>)(delegateObject)).Invoke((T)data); //Does not compile
}
}
The line ((CallbackFn<T>)(delegateObject)).Invoke((T)data); does not compile for obvious reasons, however I fail to grasp the syntax required to do 2 things:
Cast delegateObject to CallbackFn<T>
Cast InterfaceBase data to InterfacedDataType<T>
Edit:
The invoke function has to be kept with the current signature:
public void Invoke(InterfaceBase data)
This function is used in a scope where there is no type information available so I cant template that function.
Example Function where invoke is used:
List<CallbackFnWraper> fnlist;
foreach(var fn in fnlist) fn.Invoke(somedata);
Edit 2:
I made a small program that is "Minimal, Complete, and Verifiable" so if anyone wants to give it a shot:
public class DataTypeBase { }
public class DataTypeDerivedA : DataTypeBase
{
public int i = 0;
}
public class DataTypeDerivedB : DataTypeBase
{
public char c = ' ';
}
public class RunEnvironment
{
public void Run()
{
DataTypeDerivedA a = new DataTypeDerivedA();
a.i = 555;
DataTypeDerivedB b = new DataTypeDerivedB();
b.c = '#';
Wrapper w1 = MakeWrapper<DataTypeDerivedA>(Test1);
Wrapper w2 = MakeWrapper<DataTypeDerivedB>(Test2);
w1.Invoke(a);
w2.Invoke(b);
}
public Wrapper MakeWrapper<T>(CallbackFn<T> fn) where T : DataTypeBase
{
Wrapper w = new Wrapper();
w.T = typeof(T);
w.delegateObject = fn;
return w;
}
public void Test1(DataTypeDerivedA data)
{
System.Console.WriteLine(data.i);
}
public void Test2(DataTypeDerivedB data)
{
System.Console.WriteLine(data.c);
}
}
public delegate void CallbackFn<T>(T data) where T : DataTypeBase;
public struct Wrapper
{
public System.Type T;
public object delegateObject;
public void Invoke(DataTypeBase data)
{
((CallbackFn<T>)(delegateObject)).Invoke((T)(data)); //Won't compile
}
}
public class Program
{
public static void Main(string[] args)
{
RunEnvironment r = new RunEnvironment();
r.Run();
}
}
Actually this turned out to be pretty simple. You simply needed to cast your delegateObject to a Delegate type and call DynamicInvoke.
public struct Wrapper
{
public System.Type T;
public object delegateObject;
public void Invoke(DataTypeBase data)
{
((Delegate)delegateObject).DynamicInvoke(data); //Will compile
}
}
Working example: http://rextester.com/CQG34502
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);
}
?
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
Is using a switch on object types really the main way of calling a common function of stored references to class objects? It doesn't have to be a 'object' value type.
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
switch(objects[i].GetType().ToString())
{
case: "SubClassOne":
SubClassOne subclass = objects[i];
subclass.Main();
break;
case: "SubClassTwo":
SubClassTwo subclass = objects[i];
subclass.Main(); //Could probably call after the switch
break;
}
}
}
}
Note: Code not parsed, so there may be serious errors.
"Stringly" typed object oriented code is such a bad idea. You (almost) never need to know the type of an object via a string.
Changing your "print" to Console.WriteLine and main to this works fine
MainClass[] stuff = new MainClass[2];
stuff[0] = new SubClassOne();
stuff[1] = new SubClassTwo();
foreach(var item in stuff)
{
item.Main();
}
If the problem is you are determined to use an array of object, AlexH has answered.
In that case, I suggest to use as keyword to perform a safe cast operation :
using System;
public class MainClass { public void Main() { print "hello world"; } }
public class SubClassOne : MainClass { }
public class SubClassTwo : MainClass { }
public class Storer
{
public void Main() {
object[] objects = new object[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
for(i=0;i<2;i++)
{
var myMainClass = objects[i] as MainClass;
if (myMainClass != null)
{
myMainClass.Main();
}
}
}
}
As wudzik said it should be even better to declare objects as a MainClass array
There are many ways of solving this in a nice way, depends on:
If you know types and there are not too much of them:
Use LINQ OfType<>(). For more details see MSDN
foreach (var item in objects.OfType<SubClassOne>())
{
item.Main();
}
foreach (var item in objects.OfType<SubClassTwo>())
{
item.Main();
}
If there are many types, just introduce common interface
interface ISharedApi
{
void Main();
}
class SubClassOne : ISharedApi
class SubClassTwo : ISharedApi
And implement this/mark each type by it, then you just need single loop:
var objects = new List<ISharedApi>();
objects.Add(new SubClassOne());
objects.Add(new SubClassTwo());
foreach (var item in objects)
{
item.Main();
}
You should implement a more object oriented solution. Instead of creating an array consisting of objects you should make MainClass abstract and define an abstract method Main. After that you should implement Main in you sublclasses.
In this way you can exchange your code to:
using System;
public abstract class MainClass { public abstract void Main(); }
public class SubClassOne : MainClass {
public override void Main() { print "SubClassOne, hello world"; }
}
public class SubClassTwo : MainClass {
public override void Main() { print "SubClassTwo, hello world"; }
}
public class Storer
{
public void Main() {
MainClass[] objects = new MainClass[2];
objects[0] = new SubClassOne();
objects[1] = new SubClassTwo();
foreach(MainClass mc in objects)
{
mc.Main();
}
}
}
class Test
{
public delegate void FruitDelegate(Fruit f);
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = del; // Cannot implicitly convert type 'Action<T>' to 'FruitDelegate
}
}
Fruit is an empty class. Both of these delegates have the same signature.
I cannot seem to get any of this working. Maybe it would help if I explained what I am trying to do (provide some context).
I want to create a class that has a generic static method that provides a type and a method callback (like the above example).
The problem I am having is that the delegate contains a parameter and I don't want to have to cast it within the method callback. For example, I want this:
public void SomeMethod()
{
Test.Notify<Apple>(AppleHandler);
}
private void AppleHandler(Apple apple)
{
}
Instead of this:
public void SomeMethod()
{
Test.Notify<Apple>(AppleHandler);
}
private void AppleHandler(Fruit fruit)
{
Apple apple = (Apple)fruit;
}
Is this kind of thing possible?
is this what you want?
static void Main(string[] args)
{
Program p = new Program();
p.SomeMethod();
}
public class Fruit
{ }
public class Apple : Fruit { }
public delegate void FruitDelegate<in T>(T f) where T : Fruit;
class Test
{
public static void Notify<T>(FruitDelegate<T> del)
where T : Fruit, new()
{
T t = new T();
del.DynamicInvoke(t);
}
}
private void AppleHandler(Apple apple)
{
Console.WriteLine(apple.GetType().FullName);
}
public void SomeMethod()
{
FruitDelegate<Apple> del = new FruitDelegate<Apple>(AppleHandler);
Test.Notify<Apple>(del);
}
There is good reason you cannot do this. Suppose the rest of your method was:
class Test
{
public delegate void FruitDelegate(Fruit f);
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = del;
f(new Banana()); //should be legal, but del may be Action<Apple>
}
}
That would definitely not work, so the compiler is correct here.
What about something like this?
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = fruit => del((T)fruit);
}
The FruitDelegate instance, when invoked, would throw an InvalidCastException if, say, an AppleHandler was invoked with a Banana argument.