Func Chain - Method Name Expected - c#

My intentions is to chain few methods in Func and execute them one by one to get response regarding Function executed successfully or not. Below is my code but unable to Invoke func after getting it from GetInvocationList because it expecting some Method Name. Kindly Advise to fix it...
Func<bool> funcList = null;
funcList += Init;
funcList += Process;
foreach(var func in funcList.GetInvocationList()) {
bool execuationStatus = func();
}

Change your method to :
Func<bool> funcList = null;
funcList += Init;
funcList += Process;
foreach (var func in funcList.GetInvocationList())
{
var fn = func as Func<bool>;
bool execuationStatus = fn();
}
GetInvokationList returns Delegate[] and you cannot invoke on it. There is difference between Delegate class vs delegate keyword. As per MSDN documentation :
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.
Most languages implement a delegate keyword, and compilers for those
languages are able to derive from the MulticastDelegate class;
therefore, users should use the delegate keyword provided by the
language.

Related

Delegate Instantiate and Invoke Syntax

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

Delegate types and covariance with a generic delegate type

I would like to maintain a list of delegates (here: "mCommandHandlers"). Since they're generic delegates, I actually defined a second type of delegates such that I can maintain such a list:
public delegate void CommandHandler<TCommand>(TCommand command) where TCommand : ICommand;
public delegate void ICommandHandler(ICommand command);
Dictionary<Type, ICommandHandler> mCommandHandlers;
I would use the first type for compile-time advantages, such as knowing exactly what kind of TCommand is being used in the implementation of my delegate:
RegisterHandler<ResourceCommand>((command) =>
{
if (command != null)
{
ResourceManager.ResourceReceived(command.ResourceName, command.ResourceHash, command.ResourceData);
}
});
Inside RegisterHandler, I would now like to do the following:
public void RegisterHandler<TCommand>(CommandHandler<TCommand> handler) where TCommand : ICommand
{
mCommandHandlers.Add(typeof(TCommand), handler);
}
But I get the following error message:
Error 3 Argument 2: cannot convert from
CommandHandler<TCommand>' to
'ICommandHandler'
Why is this? Should the compiler see that in fact my first delegate type demands the argument to be at least of type ICommand, assuring that the delegate instance conforms to the signature of the second delegate type as well?
The problem is the two delegate types simply aren't compatible. In order to make this work you are going to need to add an indirection layer which converts the arguments between ICommand and TCommand.
public void RegisterHandler<TCommand>(CommandHandler<TCommand> handler)
where TCommand : ICommand
{
mCommandHandlers.Add(
typeof(TCommand),
(command) => handler((TCommand)command);
);
}
Should the compiler see that in fact my first delegate type demands the argument to be at least of type ICommand, assuring that the delegate instance conforms to the signature of the second delegate type as well?
There are two problems here.
Firstly, delegate variance doesn't allow for an implicit reference conversion of one delegate type to another - it allows you to create a new delegate instance from a compatible existing one.
Secondly, you've got the variance the wrong way round CommandHandler<TCommand> will only accept a specific type of command... whereas ICommandHandler will accept any ICommand.
So suppose we could do this:
CommandHandler<FooCommand> fooHandler = HandleFoo;
ICommandHandler generalHandler = new ICommandHandler(fooHandler);
Then we could call:
generalHandler(new BarCommand());
... how would you expect the HandleFoo method to cope with that?
There is a conversion from ICommandHandler to CommandHandler<TCommand> for any particular TCommand, because when the new delegate is called, that will always be valid. Sample code:
using System;
delegate void CommandHandler<TCommand>(TCommand command)
where TCommand : ICommand;
delegate void ICommandHandler(ICommand command);
interface ICommand {}
class Command : ICommand {}
class Test
{
public static void Main()
{
ICommandHandler x = null;
CommandHandler<Command> y = new CommandHandler<Command>(x);
}
}
I suggest you just change your dictionary to:
Dictionary<Type, Delegate> mCommandHandlers;
Then when you need to invoke any particular delegate, you'll need to cast to the right kind of handler - which I assume you'll know due to a type parameter at that point. Or you could create a proxy handler which performs the cast, as per Jared's answer.

Cannot convert method group '' to non-delegate type 'System.Delegate'. Did you intend to invoke the method?

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).

What makes a name of a method equivalent to an action delegate?

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.

C# - Anonymous delegate

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.

Categories