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.
Related
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.
Internally, the compiler should be translating lambda expressions to methods. In that case, would these methods be private or public (or something else) and is it possible to change that?
It depends. With the current version of Visual Studio, the methods that implement lambdas are never public, but they're not always private. A simple program to test some versions of lambdas:
public class Program
{
public static void Main()
{
var program = new Program();
Try("A", program.A);
Try("B", program.B);
Try("C", program.C);
Console.ReadKey();
}
private static void Try(string name, Func<Action> generator)
{
var mi = generator().Method;
Console.WriteLine($"{name}: DeclaringType={mi.DeclaringType}, Attributes={mi.Attributes}");
}
private Action A() => () => { };
private Action B() => () => { ToString(); };
private Action C()
{
var c = 1;
return () => c.ToString();
}
}
prints
A: DeclaringType=Scratch.Program+<>c, Attributes=PrivateScope, Assembly, HideBySig
B: DeclaringType=Scratch.Program, Attributes=PrivateScope, Private, HideBySig
C: DeclaringType=Scratch.Program+<>c__DisplayClass4_0, Attributes=PrivateScope, Assembly, HideBySig
A's lambda doesn't have any captures. It's created as an internal method of an empty closure class.
B's lambda captures this. It's created as a private method of the containing class.
C's lambda captures c. It's created as an internal method of a non-empty closure class.
All of this is undocumented and has changed in the past, so it would be good to avoid relying on it. What matters is that when you call the anonymous method, it behaves as specified. If you need anything more than that, you shouldn't be using anonymous methods. Depending on what you're after, you might either still be able to use lambdas, but with expression trees, or you might need to create regular named methods instead.
Internally, the compiler should be translating lambda expressions to methods.
I assume by "lambda" you mean a lambda converted to a delegate type. Lambdas converted to expression tree types are certainly not generated as methods.
The compiler does in fact turn such lambdas into methods, yes. There is no requirement that it does so, but doing so is convenient.
In that case, would these methods be private or public (or something else) and is it possible to change that?
The question is somewhat incoherent. Suppose I told you that a lambda was a public method. It has no name accessible from C#; how would you take advantage of its public-ness? Accessibility modifiers apply to members with names. The very notion of accessibility domain gives the domain of a name during name resolution.
In practice of course the compiler has to generate some accessibility bits for the metadata of the uncallable-by-you method. Methods generated on closure classes are internal, as that is the most convenient way to make usage of them verifiable. Methods generated without closures can be private.
Again, none of this is required, and all of it is implementation detail subject to change. You should not be attempting to take advantage of the code generation details of the compiler.
From the CLR via C# book by Jeffrey Richter
The compiler automatically defines a new private method in the class
... The compiler creates the name of the method for you automatically
... anonymous methods generated by the compiler always end up
being private, and the method is either static or nonstatic depending
on whether the method accesses any instance members
So the method is declared as private or internal.
For example the code
class AClass {
public void SomeMethod() {
Action lambda = () => Console.WriteLine("Hello World");
lambda();
}
}
will produce IL declaration as
.field private static class [mscorlib]System.Action 'CS$<>9__CachedAnonymousMethodDelegate1'
As you can see it is private static field.
However notice that lambda expression can be optimized, if you change example to
class AClass
{
string a = "Hello World";
public void SomeMethod()
{
Action lambda = () => Console.WriteLine(a);
lambda();
}
}
compiler will optimize it and there would be no lambda declaration at all
IL_0001: ldstr "Hello World"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
As #hvd mentioned there's a difference between a lambda expression uses parameters from its surrounding environment (closure case) or not. See: Why do some C# lambda expressions compile to static methods?
So the question only makes sense for the non-closure case when the lambda expression can be converted into a delegate wrapper without having any outside dependencies.
You can pass that generated class (which basically wraps a delegate) around and it will always refer to the generated delegate in the defining assembly. So you can invoke it from anywhere if the assembly is referenced.
Just verified that passing and executing an Action defined in another assembly works although the Action.Method itself is marked internal.
// Main, first assembly
namespace ConsoleApplication1
{
public class B : IB
{
Action _action;
public void AddAction(Action act)
{
_action = act;
}
public void Invoke()
{
Console.WriteLine(_action.Target);
Console.WriteLine("Is public: {0}", _action.Method.IsPublic);
_action();
}
}
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
a.AddActionTo(b);
b.Invoke();
Console.ReadKey();
}
}
}
In other assembly:
namespace OtherAssembly
{
public interface IB
{
void AddAction(Action act);
}
public class A
{
public void AddActionTo(IB b)
{
Action act = () => { };
b.AddAction(act);
}
}
}
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);
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).
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.