Hey all, quick question on how to call this lambda or what it actually does..
public Composite CreateBuffCheckAndCast(string name, UnitSelectDelegate onUnit, CanRunDecoratorDelegate extra)
{
return new Decorator(
ret => Spells.CanBuff(name, onUnit(ret)) && extra(ret),
new Action(ret => Spells.Buff(name, onUnit(ret))));
}
Unfortunately don't have the rest of this class and haven't used Lambdas in a while.. Where does that "ret" variable come from? The calling function? Is it used to grab an IEnumerable I could see the compiler assigning it whatever type onUnit would accept..?
Solution:
ret => is used to transform Spells.CanBuff into a delegate type to be accepted by Decorator. The onUnit would also accept a delegate function parameter.
The ret variable is the parameter to the delegate (or expression tree) that the lambda expression is building. Note that the ret for the first lambda expression is a different ret to the one in the second lambda expression.
So, two delegates are created, and they are passed to the Decorator constructor, which presumably stores them to execute them later on. When each delegate is called, the caller will have to pass a value in which will be available as the ret parameter during the lambda expression's execution.
Without seeing what the signature of the Decorator constructor is, it's hard to say any more than that.
I'm not quite sure what the relevance of your second snippet of code is, I'm afraid.
A lambda is an anonymous function. So in your case, ret is the parameter to the function.
When you do say
Func<int, int> myFunc = (f) => f + 1;
You are defining an anonymous function that takes an int and returns it + 1. You are storing a reference to the anonymous function in the myFunc reference. This function has not executed, it's just been defined. You can later call the function whenever you like:
int a = myFunc(4); // a becomes 5
An Action<T> is a delegate that returns void and usually points to a lambda such as yours. a Func<T1, T2> is a delegate that takes a T1 and returns a T2, and also usually points to a lambda. There are other delegates defined for other methods that take more parameters such as Func<T1, T2, T3> and Action<T1, T2>
In your case you are handing the Decorator two anonymous functions. When it deems necessary, it will call them to do some work for it, and use the return value to further its own work.
Related
What's it called when a method that takes a lambda expression as the parameter, such as Enumerable.Where, is invoked without actually declaring a variable or method parameter in the expression?
For example, I'm familiar with this lambda expression syntax:
public string GetDigits(string input)
{
return new String(input.Where(i => Char.IsDigit(i)).ToArray());
}
However, I was surprised to find out that this can also be written as:
public string GetDigits(string input)
{
return new String(input.Where(Char.IsDigit).ToArray());
}
What's going on in that second snippet, where the Char.IsDigit() method is (apparently) being called with an implicit parameter? What is this syntax called?
Methods don't accept lambdas as parameters. They accept delegates as parameters. A lambda is just one way of creating a delegate.
Another way is supplying a method group, as is done in your second example, which can be converted to a delegate.
A similar way is to use the anonymous method feature. This was more or less replaced with lambdas when they were added though, so you don't see it much. Your example using that syntax would be:
Func<char, bool> predicate = delegate(char c) { return Char.IsDigit(c); };
Yet another way would be to create a delegate using Delegate.CreateDelegate. (This isn't something you see all that often though.)
A final way is to have a delegate variable that you got from somewhere else. (That somewhere else would have created the delegate using one of these other options.)
What's going on in that second snippet, where the Char.IsDigit() method is (apparently) being called with an implicit parameter? What is this syntax called?
It's not being called. That's the whole point. We're trying to create a delegate. A delegate is an object that keeps track of a method to be invoked, and an object that it should be invoked on. You can then invoke the delegate and it will call the method that was used to create it. So here you're not calling IsDigit, you're creating a delegate that is pointing to the IsDigit method, and that will call it whenever that delegate is invoked.
When you use a lambda you're creating a new method, possibly in a new class, (neither of which have a name you can refer to, but they'll have one at runtime) and the body of that anonymous method will call IsDigit. The lambda then resolves to a delegate pointing to that anonymous method, which maintains the semantics of the other example of having a method that when called, calls an anonymous method which, in its implementation, calls IsDigit. It's adding an extra layer of indirection (that may or may not just get optimized out at runtime) to accomplish the same thing.
The signature of Enumerable.Where is:
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
This:
input.Where(i => Char.IsDigit(i))
is equivalent to writing:
Func<char, bool> temp = i => Char.IsDigit(i);
input.Where(temp);
so it creates an anonymous function with a parameter i that calls Char.IsDigit.
This:
input.Where(Char.IsDigit)
is equivalent to
Func<char, bool> temp = Char.IsDigit;
input.Where(temp);
that is equivalent to:
Func<char, bool> temp = new Func<char, bool>(Char.IsDigit);
input.Where(temp);
so it creates a delegate to Char.IsDigit and then passes it to input.Where.
So the second one removes the "man-in-the-middle" (the anonymous function). In this particular case it is "legal" because the i parameter of the anonymous function is passed "as is" to Char.IsDigit. It would have been different if it was:
input.Where(i => !Char.IsDigit(i))
in this case, you can't remove the man-in-the-middle (the anonymous function).
There is no name for all of this (or you could call the first "creating and passing a delegate to an anonymous function" and the second "creating and passing a delegate created from a method group"... but they aren't beautiful catchphrases, they are more a description of what you are doing)
Because the compiler will implicitly cast the method group to a delegate if it finds a single method that matches the expected signature, in this case a delegate taking a single char as input and returning a bool.
Your Where expects a Func<char, bool>, which is a delegate for methods that take a char argument and return a bool. Anything that matches this delegate is a valid argument for this Where.
The lambda you wrote initially matches this delegate by type inference: the compiler expects that i is char, based on the generic parameter of the enumerable source - and infers the return type as bool, because that's what the method call expression inside the lambda would return.
The Char.IsDigit method itself also matches this. Thus, referencing the method is another valid way of expressing the same thing. This is called a method group.
The semantic equivalence of these two possible arguments for Where also makes sense if you consider that for every lambda expression, the compiler generates an anonymous method and then passes that anonymous method where the delegate was expected.
To illustrate this, consider your original snippet:
Where(i => Char.IsDigit(i))
The above gets lowered by the compiler to:
bool AnAnonymousMethod(char i)
{
return Char.IsDigit(i);
}
and then:
Where(AnAnonymousMethod)
As you can see, the lambda syntax (in cases where you don't have captured variables, like here) is just syntactic sugar for writing an anonymous method and then using the method group of this newly written method as the argument wherever a compatible delegate is expected.
I'm looking to get hold of a method name from a lambda expression, I'm aware it can be done this way:
GetName(() => MethodA());
My issue is that if MethodA takes any args, you have to supply them just to satisfy the compiler about the expression (after all, how can it know you're not actually executing it?)
I'd like to be able to do:
GetName(() => MethodA);
Is there a way of doing this?
NOTE: This is not a duplicate, this is dealing with a Method Group and not an actual "invocation" of a method.
Certainly. If you have your GetName method take an Expression<Func<Action>> as a parameter, for example, then you can pass () => MethodA into it, as long as MethodA is convertible to the same delegate signature as Action.
void Main()
{
Expression<Func<Action>> x = () => Foo;
Expression<Func<Func<int>>> y = () => Foo2;
var xName = ((MethodInfo)((ConstantExpression)((MethodCallExpression)((UnaryExpression)x.Body).Operand).Object).Value).Name;
}
void Foo(){}
int Foo2(){return 0;}
You can write your GetName method to examine the given expression and extract out the name of the method group from it. However, there are two things you should keep in mind.
Even if your lambda expression appears to "call" a method, it's only an expression and won't actually generate a call to that method.
Trying to capture a method group this way will make it very difficult to distinguish between overloaded methods with the same name.
For that reason, I have to imagine you'd be better off using a more traditional approach that does involve a method call expression.
For the case, of a void-returning parameterless method, the signature of GetName could look like this:
string GetName(Expression<Func<Action>> methodExpression)
That Action in there is a problem, to make it work for methods with other signatures, you would need to add lots of overloads for other delegate types.
A solution to this is to make GetName generic and let the user specify the delegate type:
string GetName<T>(Expression<Func<T>> methodExpression)
…
GetName<Action>(() => MethodA)
The problem with this approach is that T can be any type, not just a delegate, so it's very easy to call this version of GetName incorrectly, especially since GetName(() => MethodB()) will often compile (specifically, when MethodB returns something), due to type inference.
And type constrains won't help you here, you can't write where T : Delegate.
I have a method like
void Test(Func<bool> f)
{
f.Invoke();
}
I pass in the Test( ()=>GetItem("123") )
f.Invoke() actually called GetItem("123").
I want to know how does f know GetItem has a parameter?
Your function Test takes a function as a parameter. It will invoke whatever function is passed in as an argument.
In this case, when you create your lambda () => GetItem("123"), you are creating a function that takes no arguments, and invokes GetItem("123").
Test has no knowledge about the value of the parameter passed to GetItem, nor does it need to, because the value of the parameter is hardcoded in the lambda.
You're question is a bit confusing. F doesn't know what's required by Getitem.
When you created the lambda, a "pointer" was returned to the place in the memory where a method is located. That method contains the line of code return Getitem("123").
When you invoke F, what actually happens is a kind of jump to a pointer. F is like a "pointer" to that place in the memory where the function is located.
So, to answer your question, F doesn't know what Getitem needs, F just calls the function your wrote, and that function has the "123" parameter hard coded.
Remember that lambda is a type of Delegate
What you are passing to Test is a parameter-less delegate which calls your GetItem method.
So your Test method does not know anything about parameters to GetItem. It only knows about the delegate it is calling.
Test( ()=>GetItem("123") )
is equal to
Test(delegate { return GetItem("abc") ; } );
which is like calling
Test(MyMethod)
...
bool MyMethod()
{
return GetItem("123");
}
Good question. You can think of the delegate
() => GetItem("123")
as being a compiled version of the following expression tree
Expression.Lambda<Func<bool>>(
Expression.Call(
null,
typeof(X).GetMethod("GetItem"),
new Expression[] { Expression.Constant("123", typeof(string)) }
),
new ParameterExpression[0]
);
Here I am assuming that GetItem is a method defined in a class X and that its return type is declared as bool.
The point is that the delegate captures all the information it needs to be invoked. When you invoke this delegate in Test, you have no idea that the method GetItem is behind the scenes, or that it is being invoked with the parameter "123". The delegate is keeping track of that information and Test is agnostic to those details. It just wants something that it can invoke that ultimately returns a bool. In your particular instance, that bool happens to be the result of GetItem("123").
f.Invoke() actually called GetItem("123")
Actually it didn't. It called () => GetItem("123") which merely returns the value of GetItem("123"). See the difference?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have been trying to figure this out for quite sometime (reading online blogs and articlaes), but so far unsuccessful.
What are delegates? What are Lambda Expressions? Advantages and disadvantages of both? Possible best practice of when to use one or the other?
Thanks in advance.
Delegates are methods that you can use as variables, like strings etc. For example you can declare a delegate method with one argument:
delegate void OneArgumentDelegate(string argument);
It doesn't do anything, much like an interface. If you have a method in any class with one argument like this:
void SomeMethod(string someArgument) {}
It matches the signature of the delegate, and thus can be assigned to a variable of its type:
OneArgumentDelegate ThisIsAVariable = new OneArgumentDelegate(SomeMethod);
OneArgumentDelegate ThisIsAlsoAVariable = SomeMethod; // Shorthand works too
These can then be passed as arguments to methods and invoked, like so:
void Main()
{
DoStuff(PrintString);
}
void PrintString(string text)
{
Console.WriteLine(text);
}
void DoStuff(OneArgumentDelegate action)
{
action("Hello!");
}
This will output Hello!.
Lambda expressions are a shorthand for the DoStuff(PrintString) so you don't have to create a method for every delegate variable you're going to use. You 'create' a temporary method that's passed on to the method. It works like this:
DoStuff(string text => Console.WriteLine(text)); // single line
DoStuff(string text => // multi line
{
Console.WriteLine(text);
Console.WriteLine(text);
});
Lambda expressions are just a shorthand, you might as well create a seperate method and pass it on. I hope you understand it better now ;-)
Delegate is an object that hold a reference to a function. Several different delegates may point to the same function. A delegate's type defines the footprint of a function it may point to.
Lambda expression is a function that doesn't have name. The only way to execute this function is to have a delegate pointing to the function. Lambda expressions are usually defined in place where you need a delegate to a function with a given footprint. This is useful to make code less verbose and at the same time more descriptive and flexible
I would suggest that you use a named function and a delegate to it whenever you have some code that is going to be called from different places. A common example is an event listener that you want to attach to several event producers.
Another point to consider writing a separate function is the complexity of the code. It isn't going to help anyone if you write a whole program inside a lambda expression.
On the other hand, you often need some trivial processing that you want to be executed in a callback manner. This is the point where you might love the lambda expressions.
What is very nice about lambda expressions that they inherit the scope they were defined in, so that you can easily your variables inside the lambda expression, and thus pass a lot of info inside. You should be careful though, see the Remarks section of
this article.
Labdas are brilliant in conjunction with LINQ.
To conclude, I have to quote yet another must-read msdn section:
When you use method-based syntax to call the Where method in the Enumerable class (as you do in LINQ to Objects and LINQ to XML) the parameter is a delegate type System.Func. A lambda expression is the most convenient way to create that delegate. When you call the same method in, for example, the System.Linq.Queryable class (as you do in LINQ to SQL) then the parameter type is an System.Linq.Expressions.Expression where Func is any Func delegates with up to sixteen input parameters. Again, a lambda expression is just a very concise way to construct that expression tree. The lambdas allow the Where calls to look similar although in fact the type of object created from the lambda is different.
No one has mentioned anonymous delegates. You can create delegates on the fly, without declaring them:
public void Action(Func<int, int> func);
...
Action(delegate(int x) { return x*x; });
Which is just a more verbose version of the lambda syntax:
Action(x => x*x);
Also note that the lambda syntax has more aggressive type inference. Another difference is that the lambda notation can be used to declare expression trees:
public void Action(Expression<Func<int, int>>);
Action(x => x*x);
In which case what you get is not a function but a parse tree that you can examine at runtime. This is how linq queries build their sql, for example.
edit
To more directly answer the question of when to use one or the other:
You rarely need to declare a new delegate type yourself, although it is occasionally helpful. The framework provides several Func<> types, along with Action<T> and Predicate<T> which are usually all that you need.
When creating a function 'on the fly', there is no advantage to using the anonymous delegate syntax instead of the lambda syntax. Since the lambda syntax is more concise and type-inferred, prefer it.
Delegate is just pointer to function. Its just like a "variable", where you can save address to another function that will be called
public class test {
Action<int> CallUserCode;
public test(Action<int> proc){
CallUserCode = proc;
}
void foo(){
int someValue = 0;
//do some stuff that needs to call the user procedure
CallUserCode(someValue);
}
}
Lambda Expressions is too a delegate, which has simplified syntax and can "create" functions "inline".
So the previous example would be called using lambda in following way.
void bar(){
var t = new test(x => { /* do something with the value i get from foo */});
t.foo(); //here function foo gets called, which will call 'do something' AND call my lambda expression
}
There is one important difference is there where we can use lamda than delegate.
private delegate int emptymethoddel();
// Delegate for method with no params and returns int
The equivalent framework delegate type is: Func<int>
But you cannot create new delegate instance/func from parameterized method.
private int TwoArgMethod(int i, int j)
{
return i + j;
}
but, with lambda, you can get delegate for the above method.
Func<int> retmethod = () => TwoArgMethod(10, 20);
but for delegate instantiation, we cannot do as below
emptymethoddel retmethod4 = new emptymethoddel(TwoArgMethod(10,20));
// mismatch method signature
With lambda, we can get pointers to methods that doesn't match "Func" or any other variants.
As the others said, lambdas are a syntax to create delegates inline and anonymously. One thing you can do with lambdas that is not possible with traditional functions are closures. This way you can create functions at runtime with runtime information:
string mystring = SomeObject.GetMyString();
AnotherObject.OnSomeEvent += (eventparams =>
{
string newstring = string.Format(eventparams.Message, mystring);
SomeService.PrintEvent(newstring);
}
This way, mystring is incorporated into the delegate and can be used as a variable.
I have a method with the following signature:
void MyMethod(Delegate d){};
void MyMethod(Expression exp){};
void MyMethod(object obj){};
However, this fails to compile:
MyMethod((int a) => a)
with the following error:
"Cannot convert lambda expression to type 'object' because it is not a delegate type"
Why doesn't this work?
Edit: I know that this works. The compiler compiles the lambda expression to a delgate in this case I think.
void MyMethod(Func<int, int> d){};
Kind regards,
Because the type System.Delegate isn't a "Delegate". It's just the base class. You have to use a delegate type with the correct signature. Define your Method as follows:
void MyMethod(Func<int, int> objFunc)
EDIT:
MyMethod(object) doesn't work because a lambda expression has no type at it's own, but the type is inferred from the type of the location it is assigned to. So object doesn't work either. You HAVE to use a delegate type with the correct signature.
void MyMethod(Action<int> lambdaHereLol)
{
lambdaHereLol(2);
}
in use:
var hurrDurr = 5;
MyMethod(x => Console.Write(x * hurrDurr));
C# is a statically typed language. The compiler needs to know the Type of everything it deals with. Lambdas are a bit hard to nail down, and sometimes the compiler can't figure it out. In my example above, if MyMethod took an object, the compiler couldn't figure out that x is an int (my example is simple, but there's nothing that says it can't be much more complex and harder to determine). So I have to be more explicit in defining the method that takes my lambda.
A lambda like (int a) => a will fit any delegate that takes an int and returns an int. Func<int,int> is just a single example, and you could easily declare one yourself with delegate int Foo(int x);. In fact this lambda expression will even fit a delegate that takes an int and returns a double, because the result of the lambda (a) is implicitly convertible to double.
In order for a lambda to be assignable to all the delegate types that it would fit, the lambda itself doesn't inherently have a type. Instead it takes on the type of the delegate you're using it as, as long as that's possible. ((int a) => a can't be assigned to Func<byte, byte> of course.)
While both Func<int, int> and the Foo delegate I defined can of course be converted to Delegate, a lambda can not be directly converted to Delegate because it is unclear what its actual signature would then be. After Delegate d = (int a) => a, would d be Foo, or Func<int, int>, or even Func<int, double>? All are valid possibilities, and the compiler has no idea what you intended. It could make a best guess, but C# is not the kind of language that does that kind of guesswork. This is also why you can't do something like var = (int a) => a.
I do think the error message that the compiler gives for Delegate d = (int a) => a; is very unclear:
Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
Intuitively you would think Delegate is a delegate type, but that's not how things work. :)
Try this:
void MyMethod(Action<int> func) { }
You need to a strongly-typed delegate as a parameter to the method. The reason the other calls fail is because the C# compiler will not allow you to pass a lambda expression to a method expecting an Object because a lambda expression isn't necessarily always a delegate in all cases. This same rule applies for passing the lambda expression as a Delegate.
When you pass the lambda to a function like I have showed above, the compile can safely assume that you want the lambda expression to be converted to a specific delegate type and does so.
It's simply the nature of the compiler that you need to explicitly cast a delegate object to Delegate when passing it as a parameter of type Delegate. In fact, lambda expressions complicate things even further in that they are not implicitly convertable to delegates in this case.
What you require is a double cast, as such:
MyMethod((Delegate)(Func<int, int>)((int a) => a));
which of course corresponds to the method signature:
void MyMethod(Delegate d);
Depending on your situation, you may want to define a parameter of type Func<int> rather than Delegate (though I would hesitate adding an overload, just because it adds unnecessary complexity in honesty).
The reason this fails is the same reason an expression like "object del = (int a) => a" or even "var del = (int a) => a" fails. You might think that the compiler could figure out the type of your lambda expression since you explicitly give the type of the argument, but even knowing that the expression takes an int and returns an int, there are a number of delegate types it could be converted to. The Func delegate type is the one most used for generic functions such as this, but that is just a convention and nothing the compiler is aware of.
What you need to do is to cast the lambda expression to a concrete delegate type in order to have the compiler select the Delegate overload, either using the normal cast syntax (Func)((int a) => a), or using the delegate constructor syntax new Func((int a) => a).
Also, you normally do not want to use the untyped Delegate class unless you need to invoke something differently depending on the number of argument it accepts. It's almost always better to accept a Func or Action for things like callbacks.