I am trying to learn Action delegate and lambda in C#.
So far I came to know that Action delegate encapsulates a method that does not have any parameter and returns void.
If we want to encapsulate a method having a parameter then we should use Action<T>. In the code which I am sharing, the method is having int parameter. And I am using Action delegate instead of Action<T>. Still I am able to invoke the method.
I am not able to understand this. Could anyone please explain the reason?
public static void Fourth(Action action)
{
Console.WriteLine("Fourth invoked");
action();
}
public static void Third(int x)
{
Console.WriteLine("Third invoked");
int result;
result = 3 + x;
Console.WriteLine(result);
}
Action a2 = () => Third(50);
Fourth(a2);
This line Action a2 = () => Third(50); creates a new parameter less method, which executes the Third() method.
If you want to assign the Third method to a2. You should write Action<int> a2 = Third;. Which will result in calling a2(50);
It's easy to get confused here.
a2 is not encapsulating the method Third. It uses an anonymous method declared via your lambda
() => Third(50);
This is converted by the compiler to a method in your class like that:
private static void SomeSpecialName() // so special that the name can't be used in C#, hence anonymous
{
Third(50);
}
and it is that SomeSpecialName() (having no arguments) method that a2 now refers to.
Related
I can call a non-void function from a lambda that's assigned to an Action (which expects a void return type):
static bool foo() { return true; }
...
// Action action = foo; // This gives a compile error though.
Action action = ()=>foo(); // This compiles
Initially I noticed this while looking at an example of List.ForEach(). I could execute a non-void function from the lambda and it compiled.
At first this seemed counter-intuitive, and made me think you can assign non-void functions to a void delegate (void acting like a sort of contravariant), but Action action = foo; didn't work.
So now I assume what's happening is that the lambda becomes void because that's the expected return type, so it discards the return type of the non-void function it calls. Is that correct?
Your example
Action action = ()=>foo();
is just like any other method:
public void MyTestMethod()
{
// do something
foo();
// do some more
}
This is totally legal in C# (though some static analyzers would warn you that you don't use foo()'s return value).
THe second example:
action = foo;
does not work, because foo itself is a method with a return type and therefor can only be assigned to a variable of type Func<bool>, but not to Action. The lambda () => foo() on the other hand has no return type and is a valid Action.
Well, in this line of code :
Action action = ()=> foo(); // This compiles
You actually create another method that runs your function using closure :
void AnonymousMethod()
{
foo();
}
To assign another method to a delegate that invokes method foo is not the same as assign foo method to delegate directly. And that's why line of code :
Action action = foo;
will not compile, because Action delegate has return type of void and method foo doesn't.
Here's my attempt at calling an existing generic method with a type argument. 'Strongly typed reflection' may not be a suitable term, but it basically means finding and invoking the reflected method without using a name string.
public class TestClass
{
public static void Test(Type type)
{
InvokeTestMethodWithType(type);
}
private void Test<T>() { ... }
private static void InvokeTestMethodWithType(Type type)
{
// This doesn't compile! - can I find Test<> using this approach?
Expression<Func<TestClass, Action>> ex = x => x.Test<>;
// invoke it
((MethodCallExpression)ex.Body).Method.MakeGenericMethod(type).Invoke(new TestClass(), null);
}
}
Sample call would end up call the private Test().
TestClass.Test(typeof(Foo))
As you can see, I'm struggling with the expression and not entirely sure if it can be executed in this manner.
Do I have to dummy invoke the action in the expression like this post?
x => x.Test<object>()
The trick I use is simple: pass a fake generic type argument:
Expression<Func<TestClass, WhateverTestReturns>> ex = x => x.Test<string>();
// invoke it
((MethodCallExpression)ex.Body)
.Method
.GetGenericMethodDefinition()
.MakeGenericMethod(type)
.Invoke(new TestClass(), null);
The method call expression will then contain a method info for Test<string>(), but you can easily use GetGenericMethodDefinition to remove the generic argument, and then MakeGenericMethod to put a different one back in its place.
You don't even need to use Expression in a case like this - simply cast TestClass.Test<string> to a delegate, and you'll have a Method property that gives you the same method info.
I have just seen following code:
class X
{
static Action Ac()
{
return ..some other code
}
}
What does it mean? I have never seen a delegate with its body declared.
That's not an Action delegate with its body declared. That's a static method of the X class called Ac(), with a return type of Action; that is, it's a class method that returns an Action delegate. The body presumably creates an Action object to return from the method.
To put it another way: it is a regular static method, which happens to return Action instead of something like string or int.
Delegate object which references anonymous method is declared something like (using old syntax and omitting lambda notation):
Action<int> action = delegate (int x) {
//this is a body of anonymous method
//which is referenced by a delegate object action of type Action<int>
Console.WriteLine (x);
};
And than called like:
action(5);
It exist something like Action but which can encapsulate method with signature:
void SomeFunc(IDictionary<string,class>), I try solve this:
private void RefreshContactList()
{
var freshFriends = Service.GetAllFriends(Account);
new System.Action(RefreshContactsData(freshFriends)).OnUIThread();
}
private void RefreshContactsData(IEnumerable<KeyValuePair<string, UserInfo>> freshFriends)
{
//...
}
If I understand you correctly you can use generic Action delegate. You can write then:
Action<IDictionary> myAction; //with one parameter
Action<IDictionary, int> myAction2; //with two parameters
It's not really clear what you're trying to do. Your code tries to create a delegate incorrectly - you are passing in the return value of a method invocation:
new System.Action(RefreshContactsData(freshFriends))
instead of the method itself:
new System.Action(RefreshContactsData)
However, there would be no point in creating a delegate only to call it immediately - you could just as easily call the method directly. What does OnUIThread do? What are you trying to achieve?
You do not need Action, but Action<>:
new System.Action<IEnumerable<KeyValuePair<string, UserInfo>>>(RefreshContactsData).BeginInvoke(freshFriends, null, null);
You can use the Action<> type, which encapsulates a method taking a parameter, or if you need a return value, the Func and Func<> types. For example:
static void PrintHello()
{
Console.WriteLine("Hello world");
}
static void PrintMessage(string message)
{
Console.WriteLine("Hello " + message);
}
....
Action hello = new Action(PrintHello);
Action<string> message = new Action<string>(PrintMessage);
hello();
message("my world");
produces:
Hello world
Hello my world
Note how the action is created, just referencing the method that is encapsulated within, and then it's invoked, passing the required parameter.
I want to have a library that will have a function in it that accepts an object for it's parameter.
With this object I want to be able to call a specified function when X is finished. The function that will be called is to be specified by the caller, and X will be done and monitored by the library.
How can I do this?
For reference I'm using C# and .NET 3.5
Two options for you:
Have the function accept a delegate (Action for a callback that doesn't return anything, Func for one that does) and use an anonymous delegate or Lambda Expression when calling it.
Use an interface
Using a delegate/lambda
public static void DoWork(Action processAction)
{
// do work
if (processAction != null)
processAction();
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate() { Console.WriteLine("Completed"); });
// using Lambda
DoWork(() => Console.WriteLine("Completed"));
}
If your callback needs to have something passed to it, you can use a type parameter on Action:
public static void DoWork(Action<string> processAction)
{
// do work
if (processAction != null)
processAction("this is the string");
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate(string str) { Console.WriteLine(str); });
// using Lambda
DoWork((str) => Console.WriteLine(str));
}
If it needs multiple arguments, you can add more type parameters to Action. If you need a return type, as mentioned use Func and make the return type the last type parameter (Func<string, int> is a function accepting a string and returning an int.)
More about delegates here.
Using an interface
public interface IObjectWithX
{
void X();
}
public class MyObjectWithX : IObjectWithX
{
public void X()
{
// do something
}
}
public class ActionClass
{
public static void DoWork(IObjectWithX handlerObject)
{
// do work
handlerObject.X();
}
}
public static void Main()
{
var obj = new MyObjectWithX()
ActionClass.DoWork(obj);
}
Sounds like a perfect recipe for delegates - in particular, callbacks with delegates are exactly how this is handled in the asynchronous pattern in .NET.
The caller would usually pass you some state and a delegate, and you store both of them in whatever context you've got, then call the delegate passing it the state and whatever result you might have.
You could either make the state just object or potentially use a generic delegate and take state of the appropriate type, e.g.
public delegate void Callback<T>(T state, OperationResult result)
Then:
public void DoSomeOperation(int otherParameterForWhateverReason,
Callback<T> callback, T state)
As you're using .NET 3.5 you might want to use the existing Func<...> and Action<...>
delegate types, but you may find it makes it clearer to declare your own. (The name may make it clearer what you're using it for.)
The object in question will need to implement an interface provided by you. Take the interface as a parameter, and then you can call any method that the interface exposes. Otherwise you have no way of knowing what the object is capable of. That, or you could take a delegate as a parameter and call that.
Is there a reason not to have your library provide a public event to be fired when the operation is complete? Then the caller could just register to handle the event and you don't have to worry about passing around objects or delegates.
The object implementing an interface you have provided would work, but it seems to be more the Java approach than the .NET approach. Events seem a bit cleaner to me.
You can use System.Action available in C#.NET for callback functions. Please check this sample example:
//Say you are calling some FUNC1 that has the tight while loop and you need to
//get updates on what percentage the updates have been done.
private void ExecuteUpdates()
{
Func1(Info => { lblUpdInfo.Text = Info; });
}
//Now Func1 would keep calling back the Action specified in the argument
//This System.Action can be returned for any type by passing the Type as the template.
//This example is returning string.
private void Func1(System.Action<string> UpdateInfo)
{
int nCount = 0;
while (nCount < 100)
{
nCount++;
if (UpdateInfo != null) UpdateInfo("Counter: " + nCount.ToString());
//System.Threading.Thread.Sleep(1000);
}
}