It is better to explain my intention with code. So right now I have the following code:
class A, IInterfaceUsedByB
{
}
class B
{
void func(A someObject)
{
func2(someObject, 1);
func3(someObject, "string");
func4(someObject, new MyObject());
var anotherObject = someObject.NewInstance;
func2(anotherObject, 1);
.......................
}
func2(A someObject, int val);
func3(A someObject, string val);
func4(A someObject, C val);
}
Where func2, func3, func4 do need references to someObject. I want to change this to
void func(A someObject)
{
with(someObject,
() =>
{
func2(1);
func3("string");
func4(new MyObject());
}
);
var anotherObject = someObject.NewInstance;
with(anotherObject,
() =>
{
func2(1);
.......................
}
);
}
Or even better to
void func(A someObject)
{
func2(1);
func3("string");
func4(new MyObject());
}
So that I don't have to drag this someObject around, but I should still be able to use it inside func2,3,4. In other words it's like setting some context object for a particular code block. I can use any of the three languages (C#, F# or IronPython) for this.
UPDATE In the ideal solution class B would be independent of A. func* functions only depend on a small interface of A consisting of 2 methods.
UPDATE2 The someObject can be different for different function calls.
UPDATE3 I don't think that there's a way to do this only with language primitives like classes, interfaces or extension methods. I think that the solution might be possible with more hackish tools, like attributes, reflection or F#'s computation workflow feature. Or maybe some dynamic features of IronPython. Essentially what I'm trying to do is to create a small embedded DSL.
Partial function application might work for you here.
// object for example first param
var objectInstance = new object();
// partial function application
var func2Partial = new Action<int>((i) => func2(objectInstance, i));
func2Partial(5);
If func2 returns something then you'll need to use Func<> rather than Action<>
Alternatively, as per my comment below an extension method may be an option also.
internal static class IInterfaceUsedByBExtender
{
internal static void Func2(this IInterfaceUsedByB obj, int value)
{
}
}
// caller
someObject.Func2(5);
Another option may be the pipe operator in F#. I have v. basic F# knowledge but I think you can define a function with two params and use the pipe operator to fill the value for the first param. So something like:
let printnums x y = printfn "%A - %A" x y;;
Can be called by
4 |> printnums 5;;
Which outputs:
4 - 5
With func2 you'd have something like
let func2 obj, num = ...;
someObject |> func2 1;;
More examples of this: stackoverflow: Piping F# Parameters
I hope this helps!
If all those functions operate on one object (sameObject), it looks like you should introduce a class and make them class methods. I don't know what type someObject is of, but here is an example in C#:
class Workflow<T>
where T: class
{
private readonly T _someObject;
public Workflow(T someObject)
{
_someObject = someObject;
}
public void func()
{
func2(1);
func3("string");
func4(new MyObject());
}
private void func2(int a)
{
// use _someObject here
}
private void func3(string s)
{
// ...
}
}
// usage
var flow = new Workflow(someObject);
flow.f();
class A, IInterfaceUsedByB
{
}
class B<T> where T : A
{
private T m_SomeObject;
public B(T someobject)
{
m_Someobject = someobject;
}
void func()
{
func2(1);
func3("string");
func4(new MyObject());
}
func2(int val) { //Do whatever with m_SomeObject }
func3(string val) { //Do whatever with m_SomeObject }
func4(C val){ //Do whatever with m_SomeObject }
}
You could write a function that takes a A and returns a func2 function.
For example, if the func2 return type is void (if not, then use Func < int, ReturnType>):
Action<int> func2Gen(A someObject)
{
return i => Console.WriteLine(i+someObject.ToString());
}
Then, whereever suited, you can declare
var func2=func2Gen(someObject);
and call it:
func2(1);
Related
I have several methods all with the same parameter types and return values but different names and blocks. I want to pass the name of the method to run to another method that will invoke the passed method.
public int Method1(string)
{
// Do something
return myInt;
}
public int Method2(string)
{
// Do something different
return myInt;
}
public bool RunTheMethod([Method Name passed in here] myMethodName)
{
// Do stuff
int i = myMethodName("My String");
// Do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
This code does not work but this is what I am trying to do. What I don't understand is how to write the RunTheMethod code since I need to define the parameter.
You can use the Func delegate in .NET 3.5 as the parameter in your RunTheMethod method. The Func delegate allows you to specify a method that takes a number of parameters of a specific type and returns a single argument of a specific type. Here is an example that should work:
public class Class1
{
public int Method1(string input)
{
//... do something
return 0;
}
public int Method2(string input)
{
//... do something different
return 1;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
//... do stuff
int i = myMethodName("My String");
//... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
You need to use a delegate. In this case all your methods take a string parameter and return an int - this is most simply represented by the Func<string, int> delegate1. So your code can become correct with as simple a change as this:
public bool RunTheMethod(Func<string, int> myMethodName)
{
// ... do stuff
int i = myMethodName("My String");
// ... do more stuff
return true;
}
Delegates have a lot more power than this, admittedly. For example, with C# you can create a delegate from a lambda expression, so you could invoke your method this way:
RunTheMethod(x => x.Length);
That will create an anonymous function like this:
// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
return x.Length;
}
and then pass that delegate to the RunTheMethod method.
You can use delegates for event subscriptions, asynchronous execution, callbacks - all kinds of things. It's well worth reading up on them, particularly if you want to use LINQ. I have an article which is mostly about the differences between delegates and events, but you may find it useful anyway.
1 This is just based on the generic Func<T, TResult> delegate type in the framework; you could easily declare your own:
public delegate int MyDelegateType(string value)
and then make the parameter be of type MyDelegateType instead.
From OP's example:
public static int Method1(string mystring)
{
return 1;
}
public static int Method2(string mystring)
{
return 2;
}
You can try Action Delegate! And then call your method using
public bool RunTheMethod(Action myMethodName)
{
myMethodName(); // note: the return value got discarded
return true;
}
RunTheMethod(() => Method1("MyString1"));
Or
public static object InvokeMethod(Delegate method, params object[] args)
{
return method.DynamicInvoke(args);
}
Then simply call method
Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));
Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));
In order to provide a clear and complete answer, I'm going to start from the very beginning before showing three possible solutions.
A brief introduction
All .NET languages (such as C#, F#, and Visual Basic) run on top of the Common Language Runtime (CLR), which is a VM that runs code in the Common Intermediate Language (CIL), which is way higher level than machine code. It follows that methods aren't Assembly subroutines, nor are they values, unlike functional languages and JavaScript; rather, they're symbols that CLR recognizes. Not being values, they cannot be passed as a parameter. That's why there's a special tool in .NET. That is, delegates.
What's a delegate?
A delegate represents a handle to a method (the term handle is to be preferred over pointer as the latter would be an implementation detail). Since a method is not a value, there has to be a special class in .NET, namely Delegate, which wraps up any method. What makes it special is that, like very few classes, it needs to be implemented by the CLR itself and couldn't be simply written as a class in a .NET language.
Three different solutions, the same underlying concept
The type–unsafe way
Using the Delegate special class directly.
Example:
static void MyMethod()
{
Console.WriteLine("I was called by the Delegate special class!");
}
static void CallAnyMethod(Delegate yourMethod)
{
yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}
static void Main()
{
CallAnyMethod(MyMethod);
}
The drawback here is your code being type–unsafe, allowing arguments to be passed dynamically, with no constraints.
The custom way
Besides the Delegate special class, the concept of delegates spreads to custom delegates, which are declarations of methods preceded by the delegate keyword. They are type–checked the same way as “normal” method invocations, making for type-safe code.
Example:
delegate void PrintDelegate(string prompt);
static void PrintSomewhere(PrintDelegate print, string prompt)
{
print(prompt);
}
static void PrintOnConsole(string prompt)
{
Console.WriteLine(prompt);
}
static void PrintOnScreen(string prompt)
{
MessageBox.Show(prompt);
}
static void Main()
{
PrintSomewhere(PrintOnConsole, "Press a key to get a message");
Console.Read();
PrintSomewhere(PrintOnScreen, "Hello world");
}
The standard library's way
Alternatively, you can stick with a delegate that's part of the .NET Standard:
Action wraps up a parameterless void method;
Action<T1> wraps up a void method with one parameter of type T1;
Action<T1, T2> wraps up a void method with two parameters of types T1 and T2, respectively,
and so forth;
Func<TR> wraps up a parameterless function with TR return type;
Func<T1, TR> wraps up a function with TR return type and with one parameter of type T1;
Func<T1, T2, TR> wraps up a function with TR return type and with two parameters of types T1 and T2, respectively;
and so forth.
However, bear in mind that by using predefined delegates like these, parameter names won't be self-describing, nor is the name of the delegate type meaningful as to what instances are supposed to do. Therefore, refrain from using them in contexts where their purpose is not absolutely self-evident.
The latter solution is the one most people posted. I'm also mentioning it in my answer for the sake of completeness.
The solution involves Delegates, which are used to store methods to call. Define a method taking a delegate as an argument,
public static T Runner<T>(Func<T> funcToRun)
{
// Do stuff before running function as normal
return funcToRun();
}
Then pass the delegate on the call site:
var returnValue = Runner(() => GetUser(99));
You should use a Func<string, int> delegate, that represents a function taking a string argument and returning an int value:
public bool RunTheMethod(Func<string, int> myMethod)
{
// Do stuff
myMethod.Invoke("My String");
// Do stuff
return true;
}
Then invoke it this way:
public bool Test()
{
return RunTheMethod(Method1);
}
While the accepted answer is absolutely correct, I would like to provide an additional method.
I ended up here after doing my own searching for a solution to a similar question.
I am building a plugin driven framework, and as part of it I wanted people to be able to add menu items to the applications menu to a generic list without exposing an actual Menu object because the framework may deploy on other platforms that don't have Menu UI objects. Adding general info about the menu is easy enough, but allowing the plugin developer enough liberty to create the callback for when the menu is clicked was proving to be a pain. Until it dawned on me that I was trying to re-invent the wheel and normal menus call and trigger the callback from events!
So the solution, as simple as it sounds once you realize it, eluded me until now.
Just create separate classes for each of your current methods, inherited from a base if you must, and just add an event handler to each.
Here is an example Which can help you better to understand how to pass a function as a parameter.
Suppose you have Parent page and you want to open a child popup window. In the parent page there is a textbox that should be filled basing on child popup textbox.
Here you need to create a delegate.
Parent.cs
// declaration of delegates
public delegate void FillName(String FirstName);
Now create a function which will fill your textbox and function should map delegates
//parameters
public void Getname(String ThisName)
{
txtname.Text=ThisName;
}
Now on button click you need to open a Child popup window.
private void button1_Click(object sender, RoutedEventArgs e)
{
ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor
p.Show();
}
IN ChildPopUp constructor you need to create parameter of 'delegate type' of parent //page
ChildPopUp.cs
public Parent.FillName obj;
public PopUp(Parent.FillName objTMP)//parameter as deligate type
{
obj = objTMP;
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
obj(txtFirstName.Text);
// Getname() function will call automatically here
this.DialogResult = true;
}
If you want to pass Method as parameter, use:
using System;
public void Method1()
{
CallingMethod(CalledMethod);
}
public void CallingMethod(Action method)
{
method(); // This will call the method that has been passed as parameter
}
public void CalledMethod()
{
Console.WriteLine("This method is called by passing it as a parameter");
}
If the method passed needs to take one argument and return a value, Func is the best way to go. Here is an example.
public int Method1(string)
{
// Do something
return 6;
}
public int Method2(string)
{
// Do something different
return 5;
}
public bool RunTheMethod(Func<string, int> myMethodName)
{
// Do stuff
int i = myMethodName("My String");
Console.WriteLine(i); // This is just in place of the "Do more stuff"
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
Read the docs here
However, if your method that is passed as a parameter does not return anything, you can also use Action. It supports up to 16 paramaters for the passed method. Here is an example.
public int MethodToBeCalled(string name, int age)
{
Console.WriteLine(name + "'s age is" + age);
}
public bool RunTheMethod(Action<string, int> myMethodName)
{
// Do stuff
myMethodName("bob", 32); // Expected output: "bob's age is 32"
return true;
}
public bool Test()
{
return RunTheMethod(MethodToBeCalled);
}
Read the documentation here
Here is an example without a parameter:
http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
with params:
http://www.daniweb.com/forums/thread98148.html#
you basically pass in an array of objects along with name of method. you then use both with the Invoke method.
params Object[] parameters
class PersonDB
{
string[] list = { "John", "Sam", "Dave" };
public void Process(ProcessPersonDelegate f)
{
foreach(string s in list) f(s);
}
}
The second class is Client, which will use the storage class. It has a Main method that creates an instance of PersonDB, and it calls that object’s Process method with a method that is defined in the Client class.
class Client
{
static void Main()
{
PersonDB p = new PersonDB();
p.Process(PrintName);
}
static void PrintName(string name)
{
System.Console.WriteLine(name);
}
}
I don't know who might need this, but in case you're unsure how to send a lambda with a delegate, when the function using the delegate doesn't need to insert any params in there you just need the return value.
SO you can also do this:
public int DoStuff(string stuff)
{
Console.WriteLine(stuff);
}
public static bool MethodWithDelegate(Func<int> delegate)
{
///do stuff
int i = delegate();
return i!=0;
}
public static void Main(String[] args)
{
var answer = MethodWithDelegate(()=> DoStuff("On This random string that the MethodWithDelegate doesn't know about."));
}
I know a refactor safe way to get the name of a property with this answer. Is there a refactor safe way to get the name of a method?
I am using C# 5 and .Net 4.5.
To illustrate what I'm trying to do:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
//I'd like to get the method names for UnitTestOne and UnitTestTwo here
//in such a way that this code will raise a compile time error if either
//the UnitTestOne or UnitTestTwo method names changes.
}
}
UPDATE: Here is a nice post that explains and provides a flexible utility method to access MethodInfos with refactor safe code. http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/
I think Jon Skeet's answer is fine if you only want to cover void parameterless methods. A more general solution would look like this:
public class MyClass
{
public void UnitTestOne(int i) { /* impl */ }
public int UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var methodCallExpressions = new Expression<Action<MyClass>>[] {
mc => mc.UnitTestOne(default(int)), //Note that a dummy argument is provided
mc => mc.UnitTestTwo()
};
var names = methodCallExpressions.Select(mce =>
((MethodCallExpression) mce.Body).Method.Name);
}
}
Note that we use an array of Expression<Action<MyClass>> in order to make a list of method calls on MyClass without knowing the return type and parameter types of each method call. Each method call expression is provided dummy variables to instantiate the expression.
Then the body of each expression is cast to a MethodCallExpression which, as the type name indicates, holds an expression which is just the calling of a method. That type has a Method property which is the MethodInfo of the method being called.
In the link you provided, a property name is extracted similarly using a MemberExpression. Using MethodCallExpression makes the examples quite similar.
By the way, you can also use Expression<Action> instead of Expression<Action<MyClass>> if you prefer. Replace the methodCallExpressions instantiation with:
var methodCallExpressions = new Expression<Action>[] {
() => this.UnitTestOne(default(int)),
() => this.UnitTestTwo()
};
I see this as mostly a stylistic decision, although it would also allow you to encapsulate method calls on a different class, using something like () => (new MyClass2()).UnitTestThree().
The simplest way is probably just to create a delegate for each method, and use the MulticastDelegate.Method property:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var actions = new Action[] { UnitTestOne, UnitTestTwo };
var names = actions.Select(x => x.Method.Name);
}
}
I have a list of methods that do pretty much the same thing, except a few differences:
void DoWork(string parameter1, string parameter2)
{
//Common code
...
//Custom code
...
//Common code
...
}
I want to streamline the solution with reusing the common code by passing custom code from another method.
I assume I have to use an action with parameters to accomplish this, but can't figure out how.
You could try the Template method pattern
Which basically states soemthing like this
abstract class Parent
{
public virtual void DoWork(...common arguments...)
{
// ...common flow
this.CustomWork();
// ...more common flow
}
// the Customwork method must be overridden
protected abstract void CustomWork();
}
In a child class
class Child : Parent
{
protected override void CustomWork()
{
// do you specialized work
}
}
The other answers are great, but you may need to return something from the custom code, so you would need to use Func instead.
void Something(int p1, int p2, Func<string, int> fn)
{
var num = p1 + p2 + fn("whatever");
// . . .
}
Call it like this:
Something(1,2, x => { ...; return 1; });
Or:
int MyFunc(string x)
{
return 1;
}
Something(1,2 MyFunc);
You would use delegates to handle this. It would likely look something like:
void DoWork(string parameter1, string parameter2, Action<string,string> customCode)
{
// ... Common code
customCode(parameter1, parameter2);
// ... Common code
customCode(parameter1, parameter2);
// ... Common code
}
If the custom code doesn't have to interact with the common code, it's easy:
void DoWork(..., Action custom)
{
... Common Code ...
custom();
... Common Code ...
}
Assuming you need to use the two string parameters in the custom code, the following should get the job done. If you don't actually care about the results of the custom code, you can replace Func<string, string, TResult> with Action<string, string>. Additionally, if your custom code needs to process results from the common code above it, you can adjust the parameter types that your Func<> (or Action<>) takes in and then pass in the appropriate values.
void DoWork(string parameter1, string parameter2, Func<string, string, TResult> customCode) {
//Common code
var customResult = customCode(parameter1, parameter2);
//Common code
}
Using Func<T, TResult>: http://msdn.microsoft.com/en-us/library/bb534960
Using Action<T>: http://msdn.microsoft.com/en-us/library/018hxwa8
Is there any way to do something like this in C#?
public void DoSomething(string parameterA, int parameterB)
{
}
var parameters = ("someValue", 5);
DoSomething(parameters);
Close, but unfortuantely only using object (so you get lots of boxing/unboxing)
public void DoSomething(params object[] parameters)
{
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters); // this way works
DoSomething("someValue", 5); // so does this way
Not today, no. We are at present prototyping exactly that feature for a possible hypothetical future version of C#.
If you can provide a really awesome reason why you want this feature, that would be points towards actually getting it out of prototyping and into a possible hypothetical future release. What's your awesome scenario that motivates this feature?
(Remember, Eric's speculations about possible hypothetical future releases of C# are for entertainment purposes only and are not to be construed as promises that there ever will be such a release or that it will have any particular feature set.)
No need to use reflection if you first store as a delegate, but it does require a strong declaration of the delegate.
public void DoSomething(string parameterA, int parameterB)
{
Console.WriteLine(parameterA+" : "+parameterB);
}
void Main()
{
var parameters = new object[]{"someValue", 5};
Action<string,int> func=DoSomething;
func.DynamicInvoke(parameters);
}
...and you can forget about compile-time type/sanity checking of the parameter list. Probably a bad thing.
You can invoke it through reflection, but that'll incur some overhead:
using System;
using System.Reflection;
namespace SO2744885
{
class Program
{
public void DoSomething(string parameterA, int parameterB)
{
Console.Out.WriteLine(parameterA + ": " + parameterB);
}
static void Main(string[] args)
{
var parameters = new object[] { "someValue", 5 };
Program p = new Program();
MethodInfo mi = typeof(Program).GetMethod("DoSomething");
mi.Invoke(p, parameters);
}
}
}
Of course, if you can change the method signature to take an array, that'll work as well, but that will look worse in my opinion.
nope - this is not possible.
Maybe this way is more "clean":
// standard method calling
DoSomething( "Johny", 5 );
// since C# 4.0 you can used "named parameters"
DoSomething( name: "Johny", number: 5 );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters( "Johny", 5 ) );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters{ Name = "Johny", Number = 5 } );
// calling with callback for parameters initialization
DoSomething( p => { p.Name = "Johny"; p.Number = 5; } );
// overload of DoSomething method with callback, which initialize parameters
public void DoSomething( Action<DoSomethingParameters> init ) {
var p = new DoSomethingParameters();
init( p );
DoSomething( p );
}
// overload of DoSomething method for calling with simple parameters
public void DoSomething( string name, int number ) {
var p = new DoSomethingParameters( name, number );
DoSomething( p );
}
// the "main executive" method which is "doing the work"
// all posible parameters are specified as members of DoSomethingParameters object
public void DoSomething( DoSomethingParameters p ) { /* ... */ }
// specify all parameters for DoSomething method
public class DoSomethingParameters {
public string Name;
public int Number;
public DoSomethingParameters() { }
public DoSomethingParameters( string name, int number ) {
this.Name = name;
this.Number = number;
}
}
Inspired by Steven's answer:
static public void Execute<T1, T2>(this Tuple<T1, T2> parameters, Action<T1, T2> action)
{
action(parameters.Item1, parameters.Item2);
}
var parameters = Tuple.Create("someValue", 5);
parameters.Execute(DoSomething);
I like Henrik's answer, except that it imposes a somewhat weird syntax: parameters call a method on themselves. I would do it the other way around. Only problem with this approach is that it makes you explicitly cast a method to a delegate.
Anyway, here's the basic idea:
// wrapped code to prevent horizontal overflow
public static void Execute<T1, T2>
(this Action<T1, T2> action, Tuple<T1, T2> parameters) {
action(parameters.Item1, parameters.Item2);
}
And so on (for more Ts).
Usage:
var parameters = Tuple.Create("Hi", 10);
Action<string, int> action = DoSomething;
action.Execute(parameters);
You can also easily do this with a return value:
// wrapped code to prevent horizontal overflow
public static TResult Return<T1, T2, TResult>
(this Func<T1, T2, TResult> func, Tuple<T1, T2> parameters) {
return func(parameters.Item1, parameters.Item2);
}
And so on.
I'd also like to point out that just because you aren't on .NET 4.0, that doesn't mean you can't easily implement your own Tuple<T1, T2, ...> type.
you can do:
public void DoSomething(string parameterA, int parameterB)
{
}
var func = (Action)(() => DoSomething("someValue", 5));
func();
You can do this (.NET 4.0):
var parameters = Tuple.Create("someValue", 5);
DoSomething(parameters.Item1, parameter.Item2);
If they're all the same type, yes, you can do something to this effect:
public void Print(params string[] args) {
foreach (string arg in args) {
Console.WriteLine(arg);
}
}
// ...
Print("apple", "banana");
Print("apple", "banana", "cherry");
Print("apple", "banana", "cherry", "doughnut");
Otherwise, no, you can't expand parameters in place like that without using reflection. C# doesn't have the equivalent of Ruby's splat operator.
If you don't want to change the method signature why not declare a new method with the appropriate signature and use that as a proxy. Like
public void DoSomething(string parameterA, int parameterB)
{
// Original do Something
}
public void DoSomething(object[] parameters)
{
// some contract check whether the parameters array has actually a good signature
DoSomething(parameters[0] as string,(parameters[1] as int?).Value);
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters);
You can also try out some of the stuff LinFu.Reflection provides, like Late Binding. With it you can do something like this:
var dosomethingobject = new ObjectThatHasTheDoSomething();
DynamicObject dynamic = new DynamicObject(dosomethingobject);
var parameters = new object[]{"someValue", 5};
dynamic.Methods["DoSomething"](parameters);
For this you need that the DoSomething method is inside an object.
"var" just represents a particular type, it's effectively shorthand for writing a type name. In the above you're not specifying any type. The only way to do this is to make a parameter class to represent the inputs in bulk...
public void DoSomething(Parameters param)
{
...
}
var param = new Parameters("someValue", 5);
DoSomething(param);
...but this is only going to be useful in specific circumstances. You could make multiple Parameters constructors to represent different arrangements of parameters, but the function you're calling will only take ONE input - the Parameters object. So with this you're really undermining the ability to overload a function.
So, in short, no. =)
How about this in .NET 4 (for the sake of curiosity)
public void DoSomething(string parameterA, int parameterB)
{
}
public void Helper(dynamic parameter)
{
DoSomething(parameter.Parameter1, parameter.Parameter2);
}
var parameters = new {Parameter1="lifeUniverseEverything", Parameter2=42};
Helper(parameters);
How can I select the good method (I have in the example below show 2 differents way that doesn't work). I was using instead of a variable of type Object with a IF and IS to do the job but I am trying to avoid using Object and boxing/unboxing. So I thought that Generic could do the job but I am stuck here.
Here is a small snippet of code that illustrate my question:
class Program
{
static void Main(string[] args)
{
Parser p = new Parser();
ObjectType1 o1 = new ObjectType1();
p.execute(o1);
Console.Read();
}
}
class Parser
{
public T execute<T>(T obj)
{
/*
if (obj is ObjectType1)
this.action((ObjectType1)obj);
else if (obj is ObjectType2)
this.action((ObjectType2)obj);
*/
this.action(obj);
return obj;
}
private void action(ObjectType1 objectType1)
{
Console.WriteLine("1");
}
private void action(ObjectType2 objectType2)
{
Console.WriteLine("2");
}
}
class ObjectType1
{
}
class ObjectType2
{
}
Update
I do not want interface and class. Sorry. I knew that it's not the goal of the question.
Casting with (ObjectType)obj doesn't work but if you do :
if (obj is ObjectType1)
this.action(obj as ObjectType1);
else if (obj is ObjectType2)
this.action(obj as ObjectType1);
it works... why?
And... I cannot overload for all type the execute method because this method is from an Interface. This is why all need to be called from this method.
No, you can't do this. Generics don't work like C++ templates - the generic method is compiled just once. The only information that the compiler can use for overload resolution is the information it knows about within the generic method, regardless of what code uses it.
As an example to show this, here's a bit of code which may not work how you expect it to:
using System;
class Test
{
static void Main()
{
string x = "hello";
string y = string.Copy(x);
Console.WriteLine(x==y); // Overload used
Compare(x, y);
}
static void Compare<T>(T x, T y) where T : class
{
Console.WriteLine(x == y); // Reference comparison
}
}
It's hard to say the best way to proceed without knowing more about what you want to do.
Have you considered interfaces?
interface IAction
{
void action();
}
class ObjectType1 : IAction
{
void action() {
Console.WriteLine("1");
}
}
class ObjectType2 : IAction
{
void action() {
Console.WriteLine("2");
}
}
class Parser
{
public IAction execute(IAction obj)
{
obj.action();
return obj;
}
}
Edited by OP:
This solution would require to change all Business Logic Object to have this interface. This is really not a thing to do (in my situation). And, in other situation, I always prefer to have clean BusinessObject that doesn't have Interface not related with Business stuff. In my question, I want a solution that is more related with Generic/Object/Delegate method to achieve it. Thx you. This answer won't be accepted.
The class Parser has a lot of private method that are called by the execute method depending of the object type. It needs to redirect to the good method.
The compiler will do this work for you. Just use overloads.
class Parser
{
public ObjectType1 action(ObjectType1 objectType1)
{
Console.WriteLine("1");
return objectType1;
}
public ObjectType2 action(ObjectType2 objectType2)
{
Console.WriteLine("2");
return objectType2;
}
}
class ObjectType1 { }
struct ObjectType2 { }
Then, called with:
Parser p = new Parser();
p.action(new ObjectType1());
p.action(new ObjectType2());
There's no boxing/unboxing, and the appropriate method gets called.
I haven't tried it, but can you do this?
public T execute<T>(T obj)
{
this.action((T)obj);
return obj;
}
(according to comments, doesn't work)
or
public T execute<T>(T obj)
{
this.action(obj as T);
return obj;
}
(according to comments, works)
I know you're concerned about boxing/unboxing, so there could be ValueTypes involved here.
public T execute<T>(T obj)
{
this.action(obj);
return obj;
}
Supposing that action is modifying obj, and also supposing that modification is important to the caller (which is why you're returning the value back to the caller). This code has a nasty pass-by-value defect.
Consider this code:
public int execute(int obj)
{
this.action(obj);
return obj;
}
public void action(int obj)
{
obj = obj + 1;
}
Called in this way.
int x = p.execute(1);
x is 1, not 2.
Generics happens in compile time. It is best used when you want the same code to apply to different types. It is not dynamic, so it won't help you switch between methods depending on input types.
Overloading resolving as in David B's reply works, but also happens during compile time.
The code in your update does the same thing. It casts (after careful checking of types) and then uses overloading to resolve the method.
I feel that you want to switch methods based on runtime input.
You could get a more dynamic behaviour if you used Reflection.
public object execute(object obj)
{
MethodInfo m = typeof(Parser).GetMethod(
"action",
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new Type[] { obj.GetType() },
null);
m.Invoke(this, new object[] { obj });
return obj;
}
It is perhaps a little fragile, but it works in the example.
IIRC you can use the "where" clause to allow this
public T execute<T>(T obj) where : /* somthing */
{
}
I always have to Google that one my self so I'll leave it at that.
edit: reading some comments. I would not advise calling type specific code. Rather put that code in a virtual function and call that. The call signature might get long, but that's what auto complete is for.
Koodos to joshua.ewer for finding the man page