If I only register one method of one class to a delegate, I can use the delegate.Target, but when I subscripe more methods from different classes this does not work anymore. Is there another way to access the subscribers list of this delegate?
Here is the code: The foreach loop is being evaluated to null at runtime (it compiles)
public delegate void WriteMessage(string msg);
internal class Program
{
private static void Main(string[] args)
{
var myClass = new MyClass();
var writer = new WriteMessage(myClass.WriteMessage);
writer += SaySomething; //method in this class
writer += myClass.SayShit; //instance class
writer += AnotherClass.Say; //static class
foreach(string target in (string[])writer.Target)
{
Console.WriteLine(target);
}
Console.ReadLine();
}
private static void SaySomething(string msg)
{
Console.WriteLine("HI!!!!");
}
}
complete code:
http://pastebin.com/AzzRGMY9
Delegate[] list = delegate.GetInvocationList();
That will get you an array of Delegate objects, which you can use to get the list of Targets.
This is just additional information from the accepted answer, as I am looking the same information online.
If you want to invoke all registered methods upon receiving all the invocation list, you can use this code:
Delegate[] listAllRegisteredMethods = writer.GetInvocationList(); //writer is the variable based on the question example
foreach(Delegate c in listAllRegisteredMethods )
{
object[] p = { }; //Insert your parameters here inside the array if your delegate has parameters
c.DynamicInvoke(p); //Invoke it, if you have return values, assign it on a different variable
}
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'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.
friends!
So I have been writing a simple program. Basically, I have a class (3 strings, 1 int, some methods). I am initializing the values of objects of this class from a text file. I am using List for this.
The problem is that initialization is a separate function. I had List BOTH declared AND initialized in this function. However, I might need it in other functions, including "Program.Main".
Should I make a "Global" class and put make a public List< Class > ? I decided to just declare it in my Program.Main function as of now. However, I am not sure, if a List is passed by value or by reference. I found a page on the Web, which suggests using ref keyword. Now I have:
public Class FooClass
{...}
class Program
{
static void Main(string[] args)
{
List<FooClass> fooDB = new List<FooClass>;
initFromFile(ref fooDB);
}
private static initFromFile(ref List<FooClass> fooDB)
{
using (StreamReader ... )
{
while( ... )
{
...
fooDB.Add(new FooClass(args))
}
}
}//initFromFile
}//Program
Should I keep on working like this? Or are there any crucial suggestions? Maybe "ref" isn't a good practice at all?
TLDR: Should i make a global List or pass it as a reference or another way(suggest). If passing by reference, then should I use a ref keyword or is there another way?
Thanks in advance,
~~~hlfrmn
The way your program is structured is just fine, except there's no need toi use ref. List<T> is a reference type, meaning that the value that is passed to the function is actually a reference ("pointer" in C/C++ terms) to a List<T> instance. So any modifications to the list within the method will be available when the function returns.
The only reason you would use ref is if you wanted to point fooDB to a new instance:
private static initFromFile(ref List<FooClass> fooDB)
{
fooDB = new List<FooClass>; // if the parameter was not passed by reference
// this instance would not be used by the caller.
using (StreamReader ... ){
while( ... )
{
...
fooDB.Add(new FooClass(args))
}}
}//initFromFile
EDIT
Reading the first part of your question more closely, it seems like fooDB should possibly be a class member that is initialized:
class Program
{
private static List<FooClass> fooDB;
static void Main(string[] args)
{
initFromFile();
foreach(FooClass f in fooDB)
{
// do something
}
}
private static initFromFile()
{
fooDB = new List<FooClass>();
using (StreamReader ... )
{
while( ... )
{
...
fooDB.Add(new FooClass(args))
}
}
}//initFromFile
}//Program
Generic lists are reference types hence you don't need to use ref keyword.If you make a change in your list on your method, it will affect your actual list.
Unless you're trying to set the value of fooDB directly inside the initFromFile function, you don't need to pass it as a ref parameter. Note that classes in .NET are reference types, so when you pass the list to method, the method parameter refers to the same instance that was passed in (as opposed to value types). ref parameters are used to modify what value that the both the parameter and the variable that was passed into the method reference. Using ref parameters is almost never necessary in typical .NET development.
Just pass it normally, and it will work:
static void Main(string[] args)
{
List<FooClass> fooDB = new List<FooClass>;
initFromFile(fooDB);
}
private static initFromFile(List<FooClass> fooDB)
{
using (StreamReader ... )
{
while( ... )
{
...
fooDB.Add(new FooClass(args))
}
}
}
Given the code sample above, I would suggest that your initFromFile() method just return the list, i.e.
public Class FooClass
{...}
class Program
{static void Main(string[] args)
{
var fooData = initFromFile();
}
private static List<FooClass> initFromFile()
{
var fooDB = new List<FooClass>();
using (StreamReader ... ){
while( ... )
{
...
fooDB.Add(new FooClass(args))
}}
return fooDB;
}//initFromFile
}//Program
In C# language and .NET framework, could you help me with understanding delegates?
I was trying to check some code, and found that the results I received were unexpected for me. Here it is:
class Program
{
public static int I = 0;
static Func<string> del = new Func<string>(I.ToString);
static void Main(string[] args)
{
I = 10;
Console.WriteLine("{0}", del());
}
}
The answer was 0, but not 10. Why?
The reason is the following:
The way you declare the delegate it points directly to the ToString method of the static int instance. It is captured at the time of creation.
As flindeberg points out in the comments below, each delegate has a target and a method to be executed on the target.
In this case, the method to be executed is obviously the ToString method. The interesting part is the instance the method is executed on: It is the instance of I at the time of the creation, meaning that the delegate is not using I to get the instance to use but it stores the reference to the instance itself.
Later you change I to a different value, basically assigning it a new instance. This doesn't magically change the instance captured in your delegate, why should it?
To get the result you expect, you would need to change the delegate to this:
static Func<string> del = new Func<string>(() => I.ToString());
Like this, the delegate points to an anonymous method that executes ToString on the current I at the time of the execution of the delegate.
In this case, the method to be executed is an anonymous method created in the class in which the delegate is declared in. The instance is null as it is a static method.
Have a look at the code the compiler generates for the second version of the delegate:
private static Func<string> del = new Func<string>(UserQuery.<.cctor>b__0);
private static string cctor>b__0()
{
return UserQuery.I.ToString();
}
As you can see, it is a normal method that does something. In our case it returns the result of calling ToString on the current instance of I.
You need to pass in I to your function so that I.ToString() can be executed at the appropriate time (instead of at the time function is created).
class Program
{
public static int I = 0;
static Func<int, string> del = num => num.ToString();
static void Main(string[] args)
{
I = 10;
Console.WriteLine("{0}", del(I));
}
}
Here is how this should be done:
using System;
namespace ConsoleApplication1
{
class Program
{
public static int I = 0;
static Func<string> del = new Func<string>(() => {
return I.ToString();
});
static void Main(string[] args)
{
I = 10;
Console.WriteLine("{0}", del());
}
}
}
C# delegate enable encapsulate both an object and instance and a method. A delegate declaration defines a class that is derived from the class System.Delegate. A delegate instance encapsulates an invocations list, which is a list one or more method, each of which is referred to as callable entity.
learn more form
http://asp-net-by-parijat.blogspot.in/2015/08/what-is-delegates-in-c-how-to-declare.html
My guess is because int are passed by values not references, and for that reason when creating the delegate, it's a delegate to the method ToString of the current value of "I" (0).
I have the following code:
class Program
{
static void Main(string[] args)
{
new Program().Run();
}
public void Run()
{
// works
Func<IEnumerable<int>> static_delegate = new Func<IEnumerable<int>>(SomeMethod<String>);
MethodInfo mi = this.GetType().GetMethod("SomeMethod").MakeGenericMethod(new Type[] { typeof(String) });
// throws ArgumentException: Error binding to target method
Func<IEnumerable<int>> reflection_delgate = (Func<IEnumerable<int>>)Delegate.CreateDelegate(typeof(Func<IEnumerable<int>>), mi);
}
public IEnumerable<int> SomeMethod<T>()
{
return new int[0];
}
}
Why can't I create a delegate to my generic method? I know I could just use mi.Invoke(this, null), but since I'm going to want to execute SomeMethod potentially several million times, I'd like to be able to create a delegate and cache it as a small optimization.
You method isn't a static method, so you need to use:
Func<IEnumerable<int>> reflection_delgate = (Func<IEnumerable<int>>)Delegate.CreateDelegate(typeof(Func<IEnumerable<int>>), this, mi);
Passing "this" to the second argument will allow the method to be bound to the instance method on the current object...