C# - declare method in argument (delegate) - c#

In the code below I pass method B as an action to be perfomed on on the objects in the IterateObjects method.
I would like to ask whether I can explicitly declare the method in the argument instead of passing it by name, something like this:
a.IterateObjects(delegate void(string s){//method body}) Its not correct but I am sure I have seen something like that working. Could you please advise? Thank you
DelTest a = new DelTest(); //class with method IterateObjects
a.IterateObjects(B) //HERE
private void B(string a)
{
listBox1.Items.Add(a);
}
//another class ....
public void IterateObjects(Action<string> akce)
{
foreach(string a in list)
{
akce(a);
}
}

Yes you can use a lambda like so :
a.IterateObjects ( x => listBox1.Items.Add(x) );

delegate void MyFunctionDelegate(string a);
public void Main()
{
iterateObjects (delegate(string a){/*do something*/});
}
public void IterateObjects(MyFunctionDelegate akce)
{
foreach(string a in list)
{
akce(a);
}
}
http://msdn.microsoft.com/en-us/library/900fyy8e%28VS.80%29.aspx
that's it :)

You can declare function B as anonymous function at the point of calling, through a lambda expression.

You can use a lambda expression:
a.IterateObjects((string s) => listBox1.Items.Add(s))

Related

C# pass methods as parameters

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.

Pass action delegate as parameter in C#

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}"); });

Delegate with predefined parameter

I need to pass pointer to a function as a parameter. It looks like this:
void f(Action<String> a);
But what if caller knows which string will be used. And he's always knows it. Sure i can add one more parameter, but this is not cool.
Can i somehow create delegate with predefined parameter? Thanks.
EDIT:
As workaround i can do like that
void f(Action<String> a, String s)
{
a(s);
}
...
f(_delegate, "string");
As #Spo1ler commented, pass an Action instead of Action<string>:
void f(Action a)
{
a();
}
...
f(() => _delegate("string"));

Using MethodInfo.GetCurrentMethod() in anonymous methods

public static void Main(string[] args)
{
Action a = () => Console.WriteLine(MethodInfo.GetCurrentMethod().Name);
a();
}
This code will return an obscure string like so: <Main>b__0.
Is there a way of ignoring the anonymous methods and get a more readable method name?
You could capture it outside:
var name = MethodInfo.GetCurrentMethod().Name + ":subname";
Action a = () => Console.WriteLine(name);
Other than that; no.
No, there isn't. That's why it is an anonymous method. The name is automatically generated by the compiler and guaranteed to be unique. If you want to get the calling method name you could pass it as argument:
public static void Main()
{
Action<string> a = name => Console.WriteLine(name);
a(MethodInfo.GetCurrentMethod().Name);
}
or if you really want a meaningful name you will need to provide it:
public static void Main()
{
Action a = MeaningfullyNamedMethod;
a();
}
static void MeaningfullyNamedMethod()
{
Console.WriteLine(MethodInfo.GetCurrentMethod().Name);
}
If you are looking for getting the name of the function in which the anonymous method resides in you could travel the stack and get the name of the calling method. Do note though, that this would only work as long as your desired method name is one step up in the hierarchy.
Maybe there's a way of travelling up until you reach a non-anonymous method.
For more information see:
http://www.csharp-examples.net/reflection-calling-method-name/

C# enums as function parameters?

Can you pass a standard c# enum as a parameter?
For example:
enum e1
{
//...
}
enum e2
{
//...
}
public void test()
{
myFunc( e1 );
myFunc( e2 );
}
public void myFunc( Enum e )
{
// Iterate through all the values in e
}
By doing this I hope to retrieve all the names within any given enum. What would the Iteration code look like?
This!
public void Foo(Enum e)
{
var names = Enum.GetNames(e.GetType());
foreach (var name in names)
{
// do something!
}
}
EDIT: My bad, you did say iterate.
Note: I know I could just do the GetNames() call in my foreach statement, but I prefer to assign that type of thing to a method call first, as it's handy for debugging.
Use the Enum.GetNames( typeof(e) ) method, this will return an array of strings with the names.
You can also use Enum.GetValues to obtain the counterpart values.
Edit -Whoops - if you are passing the parameter as Enum, you will need to use e.GetType() instead of typeof() which you would use if you had passed the parameter in as the actual Enum type name.
You mean something like Enum.GetNames?
Enum.GetValues
Enum.GetNames
so something like...
foreach(e1 value in Enum.GetValues(typeof(e1)))
You will have trouble if you try passing an enum directly to myFunc, as in the following example:
enum e1 {something, other};
myFunc(e1); // Syntax error: "e1 is a type, but is being used like a variable"
Like this:
public void myFunc(Enum e)
{
foreach (var name in Enum.GetNames(typeof(e)))
{
Console.WriteLine(name);
}
}
correct is:
public void myFunc(Enum e)
{
foreach (var name in Enum.GetNames(e.GetTye()))
{
Console.WriteLine(name);
}
}

Categories