I have a class called Test which has a constructor to accept Action<T> and the other one accepts Func<T,T>. Please see the below snippet.
public class Test<T>
{
//constructors
public Test() { }
public Test(Action<T> action) { }
public Test(Func<T, T> action) { }
//methods with same signature of constructor
public void MyMethod1(Action<T> action) { }
public void MyMethod2(Func<T, T> action) { }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Test<string> t1 = new Test<string>(this.MyMethod1);
Test<string> t2 = new Test<string>(this.MyMethod2);
Test<string> t = new Test<string>();
t.MyMethod1(MyMethod1);
t.MyMethod2(MyMethod2);
}
public void MyMethod1(string value) { }
public string MyMethod2(string value) { return string.Empty; }
}
But below lines throws an ambiguous call error
Test<string> t1 = new Test<string>(this.MyMethod1);
Test<string> t2 = new Test<string>(this.MyMethod2);
and the interesting point is, I have two methods with the same signature of my Test class constructor which not throwing any ambiguous error
Test<string> t = new Test<string>();
t.MyMethod1(MyMethod1);
t.MyMethod2(MyMethod2);
Could anyone please help me to identify and fix the issue.
The return value of a method is not part of its signature. Only the parameters are considered. Hence, the compiler cannot distinguish between Action<T> and Func<T,T>. A detailed explanation and workarounds can be found in this StackOverflow question
You can try renaming the parameters for each of your constructors like so:
public class Test<T>
{
public Test() { }
public Test(Action<T> action) { }
public Test(Func<T,T> function) { }
}
So when you instantiate your class you can specify the name of the parameter like so:
var objectWithAction = new Test<string>(action: Method1);
var objectWithFunction = new Test<string>(function: Method2);
Fact
method / constructor overloading can recognize the correct method by the parameter types but does not include the return type.
Reason
And since in both of the mentioned constructor calls in the question the parameter is of type MethodGroup so the compiler is unable to determine the correct overload. secondly calls to the method are successful as that in not an overloading scenario.
Resolution
here are the possible options to solve the issue
wrapping the method call into an anonymous method call and let the implicit conversion to distinguish themselves.
Test<string> t1 = new Test<string>(s => this.MyMethod1(s));
Test<string> t2 = new Test<string>(s => { return this.MyMethod2(s); });
result
Alternate approach
other option is to explicitly cast the method group
Test<string> t1 = new Test<string>((Action<string>)this.MyMethod1);
Test<string> t2 = new Test<string>((Func<string, string>)this.MyMethod2);
this is bit longer then the first approach if parameters are less
here a working console application sample
class Program
{
static void Main(string[] args)
{
Test<string> t1 = new Test<string>(action: MyMethod1);
Test<string> t2 = new Test<string>(function: MyMethod2);
Test<string> t = new Test<string>();
t.MyMethod1(MyMethod1);
t.MyMethod2(MyMethod2);
}
public static void MyMethod1(string value)
{
Console.WriteLine("my method1 {0}", value);
}
public static string MyMethod2(string value)
{
Console.WriteLine("my method2 {0}", value);
return string.Empty;
}
}
public class Test<T>
{
//constructors
public Test() { }
public Test(Action<T> action)
{
object args = "action";
action.Invoke((T)args); // here you should invoke the method in order to execute it
}
public Test(Func<T, T> function)
{
object args = "function";
function.Invoke((T)args);
}
//methods with same signature of constructor
public void MyMethod1(Action<T> action)
{
object args = "Method 3";
action.Invoke((T)args);
}
public void MyMethod2(Func<T, T> action)
{
object args = "Method 4";
action.Invoke((T)args);
}
}
hope it will help you
regards
Related
How do I call a static method from a Type, assuming I know the value of the Type variable and the name of the static method?
public class FooClass {
public static FooMethod() {
//do something
}
}
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod() //works fine
if (t is FooClass) {
t.FooMethod(); //should call FooClass.FooMethod(); compile error
}
}
}
So, given a Type t, the objective is to call FooMethod() on the class that is of Type t. Basically I need to reverse the typeof() operator.
You need to call MethodInfo.Invoke method:
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod(); //works fine
if (t == typeof(FooClass)) {
t.GetMethod("FooMethod").Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
Of course in the above example you might as well call FooClass.FooMethod as there is no point using reflection for that. The following sample makes more sense:
public class BarClass {
public void BarMethod(Type t, string method) {
var methodInfo = t.GetMethod(method);
if (methodInfo != null) {
methodInfo.Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
public class Foo1Class {
static public Foo1Method(){}
}
public class Foo2Class {
static public Foo2Method(){}
}
//Usage
new BarClass().BarMethod(typeof(Foo1Class), "Foo1Method");
new BarClass().BarMethod(typeof(Foo2Class), "Foo2Method");
Note, that as 10 years have passed. Personally, I would add extension method:
public static TR Method<TR>(this Type t, string method, object obj = null, params object[] parameters)
=> (TR)t.GetMethod(method)?.Invoke(obj, parameters);
and then I could call it with:
var result = typeof(Foo1Class).Method<string>(nameof(Foo1Class.Foo1Method));
Check into the MethodInfo class and the GetMethod() methods on Type.
There are a number of different overloads for different situations.
Given the following set of classes:
public class MyClass
{
public int MyInt { get; set; }
}
public class ObjectProcessor
{
public int ProcessObject(MyClass myClass)
{
return myClass.MyInt ++;
}
}
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(x => x.ProcessObject(classToPass));
}
}
public static class FuncExecutor
{
public static void ExecuteAction<T>(Expression<Func<ObjectProcessor, int>> expression)
{
// var func = expression.Compile(); ... does having an Expression help?
// How can I get a reference to 'classToPass' at this point?
// The 'classToPass' Type is known to be 'T', in this case 'MyClass'.
}
}
From within the ExecuteAction method, how can I get a reference to the classToPass instance that was passed in to ProcessObject?
EDIT: The comments have highlighted the complexity of trying to parse Expression Trees which could vary widely in their composition.
However, in this particular case there are two facts which cut down this variation considerably:
ProcessObject will only ever take a single parameter.
The parameter type is known in advance.
Code altered to express this.
To answer very specifically:
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
classToPass.MyInt = 42;
FuncExecutor.ExecuteAction(x => x.ProcessObject(classToPass));
}
}
public class FuncExecutor
{
public static void ExecuteAction(Expression<Func<ObjectProcessor, int>> expression)
{
var lambdaExpression = (LambdaExpression)expression;
var methodCallExpression = (MethodCallExpression)lambdaExpression.Body;
var memberExpression = (MemberExpression)methodCallExpression.Arguments[0];
var constantExpression = (ConstantExpression)memberExpression.Expression;
var fieldInfo = (FieldInfo)memberExpression.Member;
var myClassReference = (MyClass) fieldInfo.GetValue(constantExpression.Value);
Console.WriteLine(myClassReference.MyInt); // prints "42"
}
}
Please note that when you pass the lambda to the ExecuteAction method, you capture a local variable reference (classToPass). The compiler will generate some code to handle that properly. More precisely, it will generate a type with a single member (a field) of type MyClass to hold the reference and use it from this point. That's why you'll get a MemberExpression in the argument expression list.
Since you can't directly manipulate this generated type, you can't just use the member expression Value property. But you can dynamically invoke the member accessor using the MemberInfo and the target reference (an instance of the compiler generated type).
I would not rely on this code.
You can read more about lambda related compiler generated code here, for example: http://thewalkingdev.blogspot.fr/2012/04/c-lambda-expressions-and-closures.html
The easiest way is to pass the instance as parameter and let ExecuteAction take care of calling the process method using that instance. To do this it is necessary to give your code a little bit of structure using a generic object processor interface:
public interface IObjectProcessor<T> {
public int ProcessObject(T instance);
}
public class MyClassProcessor : IObjectProcessor<MyClass> {
public int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
var processor = new MyClassProcessor();
FuncExecutor.ExecuteAction<MyClass>(processor, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(IObjectProcessor<T> processor, T obj) {
int result = processor.ProcessObject(obj);
}
}
This design could be a little annoying especially if your processor are "stateless" and if you really need a Func as parameter. In this case you can drop the interface and use static processors:
public class MyClassProcessor
public static int ProcessObject(MyClass myClass) {
return myClass.MyInt ++;
}
}
public class Runner {
public void Run() {
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(MyClassProcessor.ProcessObject, classToPass);
}
}
public class FuncExecutor {
public static void ExecuteAction<T>(Func<T, int> process, T obj) {
int result = process(obj);
}
}
I have a class in which I would like to store a function call. This function call can be invoked by the class but set by the parent class. I would like to externally supply the call to be made, including any parameters.
Something like...
public class TestDelegate
{
public TestDelegate()
{
TestClass tc = new TestClass(DoSomething("blabla", 123, null));
}
private void DoSomething(string aString, int anInt, object somethingElse)
{
...
}
}
public class TestClass
{
public TestClass(delegate method)
{
this.MethodToCall = method;
this.MethodToCall.Execute();
}
public delegate MethodToCall { get; set; }
}
When the TestClass class is initialized it will call the DoSomething method of the parent class with the specified parameters. I should also mention that I do not want to require the same method signature for the method called. Meaning not always (string, int, object)
Use the Action delegate type and create an instance of this from a closure:
public class TestClass
{
public TestClass(Action method)
{
MethodToCall = method;
method();
}
public Action MethodToCall { get; set; }
}
public class TestDelegate
{
public TestDelegate()
{
// Uses lambda syntax to create a closure that will be represented in
// a delegate object and passed to the TestClass constructor.
TestClass tc = new TestClass(() => DoSomething("blabla", 123, null));
}
private void DoSomething(string aString, int anInt, object somethingElse)
{
// ...
}
}
delegate isn't the name of a type - it's a keyword used to declare delegate types, and also anonymous methods.
I suspect you actually want a specific type of delegate, such as Action, which is a delegate with no parameters and a void return type. You'll then need to change your calling code as well - because currently you're calling DoSomething before you call the constructor. Sample:
public class TestDelegate
{
public TestDelegate()
{
TestClass tc = new TestClass(() => DoSomething("blabla", 123, null));
}
private void DoSomething(string aString, int anInt, object somethingElse)
{
...
}
}
public class TestClass
{
public TestClass(Action method)
{
this.MethodToCall = method;
this.MethodToCall.Invoke();
}
// Do you really need this to be writable?
public Action MethodToCall { get; set; }
}
How do I call a static method from a Type, assuming I know the value of the Type variable and the name of the static method?
public class FooClass {
public static FooMethod() {
//do something
}
}
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod() //works fine
if (t is FooClass) {
t.FooMethod(); //should call FooClass.FooMethod(); compile error
}
}
}
So, given a Type t, the objective is to call FooMethod() on the class that is of Type t. Basically I need to reverse the typeof() operator.
You need to call MethodInfo.Invoke method:
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod(); //works fine
if (t == typeof(FooClass)) {
t.GetMethod("FooMethod").Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
Of course in the above example you might as well call FooClass.FooMethod as there is no point using reflection for that. The following sample makes more sense:
public class BarClass {
public void BarMethod(Type t, string method) {
var methodInfo = t.GetMethod(method);
if (methodInfo != null) {
methodInfo.Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
public class Foo1Class {
static public Foo1Method(){}
}
public class Foo2Class {
static public Foo2Method(){}
}
//Usage
new BarClass().BarMethod(typeof(Foo1Class), "Foo1Method");
new BarClass().BarMethod(typeof(Foo2Class), "Foo2Method");
Note, that as 10 years have passed. Personally, I would add extension method:
public static TR Method<TR>(this Type t, string method, object obj = null, params object[] parameters)
=> (TR)t.GetMethod(method)?.Invoke(obj, parameters);
and then I could call it with:
var result = typeof(Foo1Class).Method<string>(nameof(Foo1Class.Foo1Method));
Check into the MethodInfo class and the GetMethod() methods on Type.
There are a number of different overloads for different situations.
Is there any way to override a class method with a lambda function?
For example with a class definition of
class MyClass {
public virtual void MyMethod(int x) {
throw new NotImplementedException();
}
}
Is there anyway to do:
MyClass myObj = new MyClass();
myObj.MyMethod = (x) => { Console.WriteLine(x); };
Chris is right that methods cannot be used like variables. However, you could do something like this:
class MyClass {
public Action<int> MyAction = x => { throw new NotImplementedException() };
}
To allow the action to be overridden:
MyClass myObj = new MyClass();
myObj.MyAction = (x) => { Console.WriteLine(x); };
No. However if you declare the method as a lambda in the first place, you can set it, though I would try to do that at initialization time.
class MyClass {
public MyClass(Action<int> myMethod)
{
this.MyMethod = myMethod ?? x => { };
}
public readonly Action<int> MyMethod;
}
This however cannot implement an interface that has a MyMethod declared, unless the interface specifies a lambda property.
F# has object expressions, which allow you to compose an object out of lambdas. I hope at some point this is part of c#.
No. Methods cannot be used like variables.
If you were using JavaScript, then yes, you could do that.
You can write this code:
MyClass myObj = new MyClass();
myObj.TheAction = x => Console.WriteLine(x);
myObj.DoAction(3);
If you define MyClass in this way:
class MyClass
{
public Action<int> TheAction {get;set;}
public void DoAction(int x)
{
if (TheAction != null)
{
TheAction(x);
}
}
}
But that shouldn't be too surprising.
Not directly, but with a little code it's doable.
public class MyBase
{
public virtual int Convert(string s)
{
return System.Convert.ToInt32(s);
}
}
public class Derived : MyBase
{
public Func<string, int> ConvertFunc { get; set; }
public override int Convert(string s)
{
if (ConvertFunc != null)
return ConvertFunc(s);
return base.Convert(s);
}
}
then you could have code
Derived d = new Derived();
int resultBase = d.Convert("1234");
d.ConvertFunc = (o) => { return -1 * Convert.ToInt32(o); };
int resultCustom = d.Convert("1234");
Depending on what you want to do, there are many ways to solve this problem.
A good starting point is to make a delegate (e.g. Action) property that is gettable and settable. You can then have a method which delegates to that action property, or simply call it directly in client code. This opens up a lot of other options, such as making the action property private settable (perhaps providing a constructor to set it), etc.
E.g.
class Program
{
static void Main(string[] args)
{
Foo myfoo = new Foo();
myfoo.MethodCall();
myfoo.DelegateAction = () => Console.WriteLine("Do something.");
myfoo.MethodCall();
myfoo.DelegateAction();
}
}
public class Foo
{
public void MethodCall()
{
if (this.DelegateAction != null)
{
this.DelegateAction();
}
}
public Action DelegateAction { get; set; }
}