I'm working with an C API in C#. In C Methods are passed as parameters and I'm trying to accomplish the same thing in C#.
in C I would call the functions the following way:
LL_SetStatusCb(OnStatusRcv);
LL_SetScanCb(scanCb);
LL_Scan();
Note that the used methods are defined in the following way:
void OnStatusRcv(ll_status_t status)
void scanCb(ll_scan_result_t *result)
In C# the methods are defined in the same way but I don't know how I can pass those methods.
C# equivalent of function pointers are delegates. You can use Func and Action to pass methods as parameters. Func delegate represents method which takes N arguments and returns value, Action delegate represents void method.
Consider this
void (* myFunction)(int parameter)
in C# would be
Action<int>
Please try this code:
create ll_scan_result_t and ll_status_t classes.
class Program
{
delegate void ActionRef<T>(ref T item);
static void Main(string[] args)
{
ll_status_t _status = new ll_status_t();
LL_SetStatusCb(_status, OnStatusRcv);
ll_scan_result_t _scan = new ll_scan_result_t();
LL_SetScanCb(ref _scan);
}
static void LL_SetScanCb(ref ll_scan_result_t status, ActionRef<ll_scan_result_t> getCachedValue)
{
//... do something
}
static void LL_SetStatusCb(ll_status_t result, Action<ll_status_t> getCachedValue)
{
//... do something
}
static void OnStatusRcv(ref ll_scan_result_t sresult)
{
//... do something
}
static void scanCb(ll_status_t s)
{
//... do something
}
}
Use the Func Delegate like below
public class myClass
{
public bool TestMethod(string input)
{
return true;
}
public bool Method1(Func<string, bool> methodName)
{
return true;
}
public void newMthod()
{
Method1(TestMethod);
}
}
In C#, the equivalent to C/C++ function pointers are delegates. A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method that has a compatible signature and return type. You can call the method through the delegate instance.
Here's an example. First, declare a delegate:
public delegate void Del(string message);
Now, Del is a delegate type which can be used to call to any method that returns void and accepts an argument of type string. Now, let's create some method matching the signature and return type of Del:
public static void DelegateMethod(string message)
{
Console.WriteLine(message);
}
Now, let's create an instance of Del and associate it with DelegateMethod, like this:
Del handler = DelegateMethod;
If you want to call DelegateMethod, you can do it by:
handler("Hello World");
Notice that since Del is a type, you can do something like this:
public static void SomeMethod(Del callback, string callbackParams)
{
callback(callbackParams);
}
Which can be used as:
SomeMethod(handler, "Hello World");
With that said, there are othes ways of working with delegates. You can use Func and Action delegates. Func is a delegate that points to a method that accepts one or more arguments and returns a value, that is, it doesn't return void. Action is a delegate that points to a method which in turn accepts one or more arguments but returns no value (returns void). In other words, you should use Action when your delegate points to a method that returns void.
Here's an example of using an Action delegate:
static void Main(string[] args)
{
Action<string> action = new Action<string>(Display);
action("Hello!!!");
Console.Read(); //Prevents from closing the command line right away.
}
static void Display(string message)
{
Console.WriteLine(message);
}
Therefore, something like
void (* funcPtr)(int) = &someFuncWithAnIntArg;
(*funcPtr)(10);
Is equivalent in C# to
Action<int> funcPtr = new Action<int>(someFuncWithAnIntArg);
funcPtr(10);
And now for a Func delegate:
static void Main(string[] args)
{
Func<int, double> func = new Func<int, double>(CalculateHra);
Console.WriteLine(func(50000));
Console.Read();
}
static double CalculateHra(int basic)
{
return (double)(basic * .4);
}
The syntax for a Func delegate accepting an argument and returning a value is like this Func<TArgument, TOutput> where TArgument is the type of the argument and TOutput is the type of returned value. There are many more types of Func (browse the left tree index) and Action (also browse the left tree index) delegates.
And last, but not least, we have the Predicate delegates which is typically used to search items in a collection or a set of data. Let's define some boilerplate code to explain:
class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
}
Then, let's try it in:
static void Main(string[] args)
{
List<Customer> customers = new List<Customer>();
customers.Add(new Customer { Id = 1, FirstName = "Stack" });
customers.Add(new Customer { Id = 2, FirstName = "Overflow" });
Predicate<Customer> pred = x => x.Id == 1;
Customer customer = customers.Find(pred);
Console.WriteLine(customer.FirstName);
Console.Read();
}
The last code snippet will print "Stack". What happened is that the Predicate delegate named prep was used as a search criteria to search in the list customers. Basically, this delegate was run on every element x of the list, and when x.Id == 1 it returns true, false otherwise. The x element where the predicate returned true is returned as the result of the Find method.
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."));
}
public static void WaitUntilElementVisible(Action<string> preAction = null)
{
preAction?.Invoke();
}
static void Main(string[] args)
{
WaitUntilElementVisible((str) => PanelHandler("in"));
}
public static void PanelHandler(string className)
{
// do something
}
I want to execute PanelHandler("in") if its not null inside the WaitUntilElementVisible() method. However the Invoke() expects a string. But the strange thing is that I'm already giving it a string when I do WaitUntilElementVisible(() => PanelHandler("in")); how can I make Invoke use the string which I pass via lambda?
I want to call WaitUntilElementVisible() in such a way that WaitUntilElementVisible() will invoke PanelHandler with "in".
Your WaitUntilElementVisible is using an Action<string> delegate which is simply a reference to a method that expects a string argument but it does not know anything about the concrete method you want to call, in your example, the reference being used is the anonymous method you create with your lambda expression (str) =>, then, that method calls your actual method but you have already passed the reference of the original method!
If you convert the anonymous method to a regular one it is easier to understand what is happening:
static void Main(string[] args)
{
WaitUntilElementVisible(MyActionMethod);
}
public static void WaitUntilElementVisible(Action<string> preAction = null)
{
preAction?.Invoke();
}
public static void MyActionMethod(string str)
{
PanelHandler("in");
}
public static void PanelHandler(string className)
{
Console.WriteLine(className);
}
As you can see the reference you are passing is to MyActionMethod and not to PanelHandler and the str parameter is not used at all.
So you need to add a string argument to your method to pass the value and then you have the reference to the method and the value you need to pass:
static void Main(string[] args)
{
WaitUntilElementVisible(PanelHandler, "in");
}
public static void WaitUntilElementVisible(Action<string> preAction = null, string value = null)
{
preAction?.Invoke(value);
}
public static void PanelHandler(string className)
{
Console.WriteLine(className);
}
Or you can remove the string requirement and simply accept any method and then your code will work:
static void Main(string[] args)
{
WaitUntilElementVisible(() => PanelHandler("in"));
}
public static void WaitUntilElementVisible(Action preAction = null)
{
preAction?.Invoke();
}
public static void PanelHandler(string className)
{
Console.WriteLine(className);
}
Now of course, you are simply telling the compiler to invoke whichever method is referenced by your action delegate.
Another option is to use a dynamically typed language such as Python ;-)
def waitUntilElementVisible(preAction = None):
if preAction is not None:
preAction()
def panelHandler(className):
print(className)
if __name__=='__main__':
waitUntilElementVisible(panelHandler('in'))
In this case this will work because references are resolved at run-time and not at compile time like in .NET.
The problem is due to your declaration of WaitUntilElementVisible, the declaration
public static void WaitUntilElementVisible(Action<string> preAction = null)
declares a delegate that will take a string parameter, that is, it is expecting that the call to WaitUntilElementVisible will look like:
WaitUntilElementVisible(someString => PanelHandler(someString));
Which would be the useful in the situation where the WaitUntilElementVisible was to provide the string to your delegate.
What you want is for the declaration of WaitUntilElementVisible to be
public static void WaitUntilElementVisible(Action preAction = null)
Which means that it expects a delegate that takes no arguments.
I have a method which accepts an Action delegate and executes the given method as shown here:
public void ExpMethod(Action inputDel)
{
inpuDel();
}
I can call above given method like this:
ExpMethod(() => {/*do something that matters*/});
Everything works fine. So far so good. Now I want to have a method which takes a generic Action delegate as an input parameter - like this:
public void ExpGenMethod(Action<string,int> inputDel)
{
// I don't know how to call the supplied delegate as it requires parameters
}
Also, I am trying to call this ExpGenMethod in this way:
ExpGenMethod(("Hi",1) => {/*do something that makes sense*/});
But it shows syntax errors. Please let me know how to use generic action delegate in this case?
The whole point of a delegate is to have a pointer to a method. Passing parameters to it while it´s being declared is therefor pointless. Instead pass the arguments for your delegate within the method that executes the delegate, in your case within ExpGenMethod:
You should do this instead:
public void ExpGenMethod(Action<string,int> inputDel)
{
inputDel("Hi", 1);
}
And call it like this:
ExpGenMethod((x, y) => {/*do something that makes sense*/});
When executing that delegate x evaluates to "Hi" and y to 1.
Typically, you'll want the heavy lifting to happen in the ExpGenMethod and in the delegate itself you'll simply be passing the parameters to the ExpGenMethod.
using System;
public class Program
{
public static void Main()
{
ExpGenMethod((options) =>
{
options.x = "Hi";
options.y = 1;
});
}
public static void ExpGenMethod(Action<Options> inputDel)
{
var options = new Options();
inputDel(options);
/* have access to x and y so do some thing useful with these values */
Console.WriteLine(options.x);
Console.WriteLine(options.y);
}
}
public class Options
{
public string x { set; get;}
public int y { set; get; }
}
(a,b) => {/*do something that matters*/} means that a and b are parameters which are going to be specified during the call. Here you are using constant so you should do something like () => { use "Hi"; use 1;} and that would get you back to your first working example.
If you want to pass parameter you cna do it this way:
public void work()
{
ExpGenMethod((a) => {/*do something that matters*/});
}
public void ExpGenMethod(Action<int> inputDel, int parameterToUse)
{
inputDel(parameterToUse);
}
As a follow on to what #HimBromBeere explained:
The keyword Action is defined as delegate:
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
So if the method is defined as:
public void ExpGenMethod(Action<string,int> inputDel)
{
inputDel("Hi", 1);
}
You can call ExpGenMethod with parameters x,y is using a Lambda expression, and see the results using Console.Writeline as follows:
ExpGenMethod((x, y) => { Console.WriteLine($"{x} {y}"); });
My code is as follows:
class PropertyRetrievalClass
{
public delegate object getProperty(string input);
public object get_Chart_1(string iput)
{
Console.WriteLine(iput);
return "";
}
public object get_Chart_2(string iput)
{
Console.WriteLine(iput);
return "";
}
public PropertyRetrievalClass() { }
}
public static void Main()
{
int i = 1;
PropertyRetrievalClass obj = new PropertyRetrievalClass();
Delegate del = Delegate.CreateDelegate(typeof(PropertyRetrievalClass), obj, "get_chart_" + i.ToString());
string output= del("asldkl");
}
It is giving me an error saying "error CS0118: 'del' is a 'variable' but is used like a 'method'"
What should I do to use this delegate? I want to call any of "get_chart_1" or "get_chart_2" function and both of them take a string input?
Thanks in advance...
You have two issues in your code.
A Delegate object is not a method, so you need to use a method on the Delegate object to invoke the method it refers
The first argument to CreateDelegate should be the delegate type, not the class containing a method you want to invoke.
Full working example:
public delegate void ParamLess();
class SomeClass
{
public void PrintStuff()
{
Console.WriteLine("stuff");
}
}
internal class Program
{
private static Dictionary<int, int> dict = null;
static void Main()
{
var obj = new SomeClass();
Delegate del = Delegate.CreateDelegate(typeof(ParamLess), obj,
"PrintStuff", false);
del.DynamicInvoke(); // invokes SomeClass.PrintStuff, which prints "stuff"
}
}
In your case, the Main method should look like this:
public static void Main()
{
int i = 1;
PropertyRetrievalClass obj = new PropertyRetrievalClass();
Delegate del = Delegate.CreateDelegate(
typeof(PropertyRetrievalClass.getProperty),
obj,
"get_Chart_" + i.ToString());
string output = (string)del.DynamicInvoke("asldkl");
}
Update
Note that CreateDelegate is case sensitive on the method name, unless you tell it not to.
// this call will fail, get_chart should be get_Chart
Delegate del = Delegate.CreateDelegate(
typeof(PropertyRetrievalClass.getProperty),
obj,
"get_chart_" + i.ToString());
// this call will succeed
Delegate del = Delegate.CreateDelegate(
typeof(PropertyRetrievalClass.getProperty),
obj,
"get_Chart_" + i.ToString());
// this call will succeed, since we tell CreateDelegate to ignore case
Delegate del = Delegate.CreateDelegate(
typeof(PropertyRetrievalClass.getProperty),
obj,
"get_chart_" + i.ToString(),
true);
The other answers have addressed the problem with your code, but I wanted to offer an alternative.
If there are a limited, finite number of methods that your retrieval class is choosing from, and they have the same signatures, this can be done much more efficiently without using reflection:
public int MethodIndex {get;set;}
public static void Main()
{
PropertyRetrievalClass obj = new PropertyRetrievalClass();
Func<string,object> getChartMethod;
switch(MethodIndex)
{
case 1:
getChartMethod = obj.get_chart_1;
break;
case 2:
getChartMethod = obj.get_chart_2;
break;
}
string output= getChartMethod("asldkl");
}
If there were a lot, you could just create an array instead of using a switch. Obviously you could just run the appropriate function directly from the switch, but I assume that the idea is you may want to pass the delegate back to the caller, and a construct like this lets you do that without using reflection, e.g.
public static Func<string,object> GetMethod
{
... just return getChartMethod directly
}
You are using the Delegate class not the delegate keyword.
You cannot call a method on Delegate type. You have to use DynamicInvoke() which is very slowwwwwww.
Try this:
string output = (string) del.DynamicInvoke(new object[]{"asldkl"});
You can only call delegates with method call syntax, if they have a known signature. You need to cast your delegate to the delegate type you defined earlier.
var del = (PropertyRetrievalClass.getProperty)Delegate.CreateDelegate(typeof(PropertyRetrievalClass.getProperty), obj, "get_Chart_" + i.ToString());
You also need to change the first argument to CreateDelegate, because it should be the delegate type. And capitalize the "C" in "get_Chart_".
And then, you will need to cast the returned object to string:
string output= (string) del("asldkl");
Or change the delegate type and the methods to have string as their return type.
I'm a c++ developer having used signals & slots in c++ which to me seems to be analogous to delegates in c#. I've found myself at a loss in searching for the functionality provided by "bind", and feel I must be missing something.
I feel like that something like the following, which is possible in c++ should be possible in c# with delegates. Here is some psudo-code for what I would do in c++:
Slot<void> someCallback;
int foo(int i)
{
std::cout << "Value: " << i << "\n";
return i;
}
int main()
{
int i = 0;
Slot<int> someCallback = bind( fun_ptr(foo), i );
++i; // added to show that late evaluation would be a non-trivial difference
int result = someCallback();
assert( result == 0 );
return 0;
}
Unfortunately, I've not been able to find any reference to binding/rebinding with regards to c# delegates. Am I missing something? Is there some radically different way to do this in c#?
In C# we do something like this:
class Program {
static Action Curry<T>(Action<T> action, T parameter) {
return () => action(parameter);
}
static void Foo(int i) {
Console.WriteLine("Value: {0}", i);
}
static void Main(string[] args) {
Action curried = Curry(Foo, 5);
curried();
}
}
Clearly the method Foo corresponds to your method Foo, just with the appropriate calls to Console.WriteLine instead of std::cout.
Next, we declare a method Curry that accepts an Action<T> and returns an Action. In general, an Action<T> is a delegate that accepts a single parameter of type T and returns void. In particular, Foo is an Action<int> because it accepts one parameter of type int and returns void. As for the return type of Curry, it is declared as an Action. An Action is a delegate the has no parameters and returns void.
The definition of Curry is rather interesting. We are defining an action using a lambda expression which is a very special form of an anonymous delegate. Effectively
() => action(parameter)
says that the void parameter is mapped to action evaluated at parameter.
Finally, in Main we are declaring an instance of Action named curried that is the result of applying Curry to Foo with the parameter 5. This plays the same role as bind(fun_ptr(foo), 5) in your C++ example.
Lastly, we invoke the newly formed delegate curried via the syntax curried(). This is like someCallback() in your example.
The fancy term for this is currying.
As a more interesting example, consider the following:
class Program {
static Func<TArg, TResult> Curry<TArg, TResult>(
Func<TArg, TArg, TResult> func,
TArg arg1
) {
return arg => func(arg1, arg);
}
static int Add(int x, int y) {
return x + y;
}
static void Main(string[] args) {
Func<int, int> addFive = Curry<int, int>(Add, 5);
Console.WriteLine(addFive(7));
}
}
Here we are declaring a method Curry that accepts a delegate (Func<TArg, TArg, TResult> that accepts two parameters of the same type TArg and returns a value of some other type TResult and a parameter of type TArg and returns a delegate that accepts a single parameter of type TArg and returns a value of type TResult (Func<TArg, TResult>).
Then, as a test we declare a method Add that accepts two parameters of type int and returns a parameter of type int (a Func<int, int, int>). Then in Main we instantiate a new delegate named addFive that acts like a method that adds five to its input parameter. Thus
Console.WriteLine(addFive(7));
prints 12 on the console.
Try the following
class Example {
static void foo(int i) {
Console.WriteLine(i);
}
public static void Main() {
Action someCallback = () => foo(5);
someCallback();
}
}
Or for something even closer to the C++ counter part
class Example {
static void foo(int i) {
Console.WriteLine(i);
}
static Action bind<T>(Action<T> action, T value) {
return () => action(value);
}
public static void Main() {
Action someCallback = bind(foo, 5);
someCallback();
}
}
Explanation. What's happening here is that I am creating a new delegate by means of a lambda expression. The lambda is the expression starting with () =>. In this case it creates a delegate accepting no arguments and producing no value. It is compatible with the type Action.