Going back to basics - a little confused on the syntax sugar for delegates. Here is my scenario:
I have a delegate which takes zero paramaters and returns void. Essentially an Action delegate with zero parameters. Code snippet below (purposefully using basic delegate syntax versus Action Delegate usage)
class Program
{
public delegate void Del(); // Declare
static void Main(string[] args)
{
Del d = MethodCalled; //Instantiate
d(); //Invoke
Console.ReadLine();
}
public static void MethodCalled()
{
Console.WriteLine("Hello");
}
}
Question: How can I combine instantiate and invocation calls in one sentence (for delegates with no return) similar to below (use-case where I have a return value coming from a Delegate:
//Instantiate & Invoke Delegate
string handler = MethodCalled("Hello");
Please note - this question is not how to write a Action Delegate equivalent using Anonymous Method or Lamda Expressions. That I know. Even in there I still have to do invocation of the delegate d().
My question is more related to how do i combine 2 statements (irrespective of the syntax used - basic delegate, Action delegate)
new SomeDelegate(SomeMethod)(SomeParameter);
Related
Is there a way to pass different methods as parameter into another method in C#? I have some code like this below
class Program
{
void Action1(string s){...}
string Func1(string s){...}
void RegisterAction(Action<string> action){...}
void RegisterFunc(Func<string, string> func){...}
void Register(????){ }
void Run()
{
RegisterAction(Action1); // ok
RegisterFunc(Func1); // ok
Register(Action1); // ?
Register(Func1); //?
}
}
I want to pass Action1 and Func1 into the same method 'Register', in which I can use reflection to implement my logic. but the Action<string>, Func<string,string>are different delegates, perhaps I will have to deal with Action<int>, Func<object> and many other types I don't want to write the 'register' methods for every action and function.
Any help? Thank you.
There is a base type - MulticastDelegate which itself has a base type of Delegate - but the problem is that you're relying on a method group conversion to a delegate type, and that requires a specific delegate type to convert to. Register(Action1) could convert the method group Action1 to any delegate type returning void and accepting a string - there can be multiple such delegates. How would the compiler know which one you mean?
What you could do is keep your RegisterAction and RegisterFunc methods, but then use a common implementation which stores the delegates in (say) a List<Delegate>.
I'm trying to store a function reference in a Delegate type for later use.
Here's what I'm doing:
class Program
{
static void Test()
{
}
static void Main(string[] args)
{
Delegate t= (Delegate)Test;
}
}
In this I'm getting following error:
Cannot convert method group 'Test' to non-delegate type 'System.Delegate'.
Did you intend to invoke the method?
Why is this happening?
You really shouldn't ever use the type Delegate to store a delegate. You should be using a specific type of delegate.
In almost all cases you can use Action or Func as your delegate type. In this case, Action is appropriate:
class Program
{
static void Test()
{
}
static void Main(string[] args)
{
Action action = Test;
action();
}
}
You can technically get an instance of Delegate by doing this:
Delegate d = (Action)Test;
But actually using a Delegate, as opposed to an actual specific type of delegate, such as Action, will be hard, since the compiler will no longer know what the signature of the method is, so it doesn't know what parameters should be passed to it.
What you are trying to do here is cast the method group Test to something. As per the spec, the only legal cast for a method group is casting it into a delegate type. This can be done either explicitly:
var t = (Delegate)Test;
or implicitly:
Delegate t = Test;
However, as the documentation says, System.Delegate itself is... not a delegate type:
The Delegate class is the base class for delegate types. However, only
the system and compilers can derive explicitly from the Delegate class
or from the MulticastDelegate class. It is also not permissible to
derive a new type from a delegate type. The Delegate class is not
considered a delegate type; it is a class used to derive delegate
types.
The compiler detects this and complains.
If you want to cast a method group to a delegate you will have to specify a delegate type with a compatible signature (in this case, Action).
consider following:
1st APPROACH:
public void f3()
{
f2();
f1();
}
and this ...
2nd APPROACH:
class Sample
{
public delegate void MyDelegate(string s);
MyDelegate obj;
public Sample()
{
obj += new MyDelegate(input);
obj+=new MyDelegate(something);
obj += new MyDelegate(someStaticMethod);
}
}
When i call f3() it will call the functions listed inside it ... same would happen when i will invoke a delegate ... so whats the use of delegate to handle some event when i can use 1st approach ... the 1st approach too encapsulates the method call..
In case of the delegate, the invocation order of the attached functions is not specified.
Also, you can attach any number of functions to it, even during runtime, from other objects, not just the hard coded ones as in the first approach. The delegate has wider usage.
First approach is static. Delegate approach allows you or a caller to determine what gets called at a later time.
I was just experimenting and ended up with the following snippet:
public static class Flow {
public static void Sequence(params Action[] steps) {
foreach (var step in steps)
step();
}
}
void Main() {
Flow.Sequence(() => F1(), () => F2());
Flow.Sequence(F1, F2); // <-- what makes this equiv to the line above?
}
void F1() { }
void F2() { }
I didn't realize that a method name alone was the same as an Action.
What is making this so?
In C#, delegates are nothing more than method pointers. They can point to existing methods in a class, or independent anonymous delegate objects altogether.
This paragraph from the above link should explain what's happening in your code:
Any method that matches the delegate's signature, which consists of the return type and parameters, can be assigned to the delegate. This makes is possible to programmatically change method calls, and also plug new code into existing classes. As long as you know the delegate's signature, you can assign your own delegated method.
That is, when resolving delegate types, what's considered are their signatures, rather than their names.
In your case, your F1() and F2() methods, taking no parameters and returning nothing, have matching signatures with the parameterless Action delegate:
public delegate void Action();
Therefore, they're implicitly convertible to Action.
If you try to pass a method with a different return type or at least one parameter, you'll get a compile-time error as it won't correspond to Action's signature.
Basically, this is kind of what is happening in the background:
void Main()
{
Flow.Sequence(new Action(delegate(){ F1(); }), new Action(delegate(){ F2(); }));
Flow.Sequence(new Action(F1), new Action(F2));
}
They're not EXACTLY equivalent, but they're very close. They would render the same results at run-time, the only difference being that the arguments in the first Sequence invocation would be an Action which invokes an anonymous method which then invokes the static methods F1 and F2; the second Sequence invocation would be an Action which invokes the static methods F1 and F2.
I hope this helps.
The compiler uses an implicit conversion from a method group to a delegate of compatible type (in this case a void returning method taking no arguments), the method names here are irrelevent.
Like Anonymous Methods ,the delegates i am declaring down using "delegate" keyword are anonymous delegates?
namespace Test
{
public delegate void MyDelegate();
class Program
{
static void Main(string[] args)
{
DelegateTest tst = new DelegateTest();
tst.Chaining();
Console.ReadKey(true);
}
}
class DelegateTest
{
public event MyDelegate del;
public void Chaining()
{
del += delegate { Console.WriteLine("Hello World"); };
del += delegate { Console.WriteLine("Good Things"); };
del += delegate { Console.WriteLine("Wonderful World"); };
del();
}
}
}
There's no such thing as an "anonymous delegate" (or rather, that's not a recognised term in the C# specification, or any other .NET-related specification I'm aware of).
There are anonymous functions which include anonymous methods and lambda expressions.
Your code shows plain old anonymous methods - although they are using the one feature lambda expressions don't have: the ability to not express the parameters at all when you don't care about them.
Your delegate collection in the example points to a number of anonymous methods. A delegate is "just a method pointer". It doesn't matter if it points to a real method or an anonymous method.
Please see http://msdn.microsoft.com/en-us/library/0yw3tz5k(VS.80).aspx
That's correct, you have assigned a number of anonymous methods to an event.
If you're using a newer version of c#, you can also do something similar with lambdas. for example:
class DelegateTest
{
public event Action del;
public void Chaining()
{
del += () => Console.WriteLine("Hello World");
del += () => Console.WriteLine("Good Things");
del += () => Console.WriteLine("Wonderful World");
del();
}
}
Yes, they are anonymous delegates (or, more specific, delegates calling an anonymous method).
Yes. Anonymous delegates cannot be referred to directly by name, so using the delegate(){} syntax means they are anonymous.
Your delegate is not anonymous. It's called MyDelegate.
Delegate in CLR is a class that derives from System.MulticastDelegate and in your case it's called MyDelegate.
You cannot directly derive from MulticastDelegate, C# compiler will stop you.
In your code when you assign delegates to del, the type/name of the delegate is inferred by compiler because you declared del as event of type MyDelegate.
They are delegates to anonymous methods. This is one way to make anonymous methods, which was available since .NET 2.0. With .NET 3.0 you can also use lambda expressions which are simpler to write (but compile to the same code). I suppose that's what you meant with "anonymouse methods". But really, they are one and the same thing.