Please guide me in getting the following line c# lambda expression code - c#

<%= MyClass.GetData(() => new[] { Html.TextBox(prefix + "Postcode", Customer.ZipCode, new { maxlength = 7 }), Html.ValidationIcon(prefix + "ZipCode") })%>
Can someone please explain me what the MyClass.GetData method is getting passed as parameter?
I don't expect a full explanation and i know that i should learn further into anonyous methods and lamda expression... But for now can you explain what the the code as from "() =>......." means?
And if you know some nice articles that builds towards understanding material like this that would be cool !

The () => new [] { ... } is a lambda expression which is short-hand syntax for an anonymous delegate. This means that you are passing in essentially the equivalent of a pointer to a function that takes no arguments, the () part indicates the arguments, and returns the results in { } braces (Html.TextBox.... etc).
Essentially, this would be equivalent to passing a method name that accomplishes the same thing, but it's more concise syntax:
MyClass.GetData(() => new[] { Html.TextBox(prefix + "Postcode", Customer.ZipCode, new { maxlength = 7 }), Html.ValidationIcon(prefix + "ZipCode") }
is the same, roughly, as creating a method, then passing that method name in.
private WebControl[] GetControls()
{
return new[] { Html.TextBox(prefix + "Postcode", Customer.ZipCode, new { maxlength = 7 }), Html.ValidationIcon(prefix + "ZipCode");
}
....
MyClass.GetData(GetControls);
p.s. Here's a good basic lambda tutorial: http://blogs.msdn.com/b/ericwhite/archive/2006/10/03/lambda-expressions.aspx

() => means an lambda that does not take any parameters. So you are passing into GetData a lambda that takes no parameters and returns a new array.

It means: Here is an anonymous delegate that takes no argument and returns an array of objects whose type will be inferred from the return values of Html.TextBox() and Html.ValidationIcon().

Related

Action<Action<string,int>> and Lambda Expression in C#

I've searched on this, but don't really know how to word the question to get the answer so far I can't find anything on nested actions like this with Lambda expressions. I can find lots of help on passing lambda expressions as parameters where the parameter is a delegate and in fact I'm doing that lots in my code. It's the nested lambda expression that's giving me problems.
I have a class with a property of type
Action<Action<string,int>> myAction
and I want to assign it with a Lambda expression. I can do it without Lambda expressions using real methods that I have elsewhere in the code. I can also do something simple like
myAction = ((a) => { a("a string", 0); });
but I would like to asign the sub-action and the action in one Lambda. Something like...
myAction = (((s,i)=>{//sub-action body here})=> { //do something here});
But this syntax doesn't work. Is there a way to do this, or do I have to define my methods in advance and do it without a Lambda expression if I want to do this?
Action<Action<string, int>> myAction = a => (new Action<string, int>((s, i) => Console.WriteLine(i + s)))("hello", 1);
myAction(null); //1hello
Console.ReadLine();
though its equal to
Action<Action<string, int>> myAction = a => Console.Writeline("1hello");
you just ignore an argument

Get custom attribute of method executed in action

Here is my example metod
[TestStep("Do something")]
private void DoSomething()
{
}
Each method which looks like the one above is executed in a way which requires logging the method parameters:
private void LogStep(Action action)
{
string stepName = "[" + action.Method.Name + "] ";
var descr = Attribute.GetCustomAttribute(action.Method, typeof(TestStepAttribute)) as TestStepAttribute;
if (descr == null)
{
this.TestLog.AddWarningMessage(
(action.Method.DeclaringType == null ? string.Empty : action.Method.DeclaringType.FullName + ".") + action.Method.Name
+ ": missing description");
return;
}
stepName += descr.Description;
this.TestLog.EndGroup();
this.TestLog.BeginGroup(stepName);
}
And here I come with a problem. Executing LogStep like
LogStep(DoSomething)
works perfectly, but when I execute it using lambda expression
LogStep(() => DoSomething())
It tells me that there are no attributes of type TestStepAttribute in that Action.
At first glance it seems to be similar to How do I get the custom attributes of a method from Action<T>? but in my case I neither can change type of Action to Expression<Action> nor I know the method name.
Any suggestion'd be helpful.
When you execute it using a lambda expression, the lambda expression itself is the method. It happens that in its body there is a method call, but there could be something else there (like new object()). The only way to get access to the attributes of this inner method is to pass the lambda expression as Expression and to analyze the expression.
In order to handle both cases you will need two overloads of LogStep. However, you cannot have LogStep(Action) and LogStep(Expression<Action>) as overloads at the same time as the calls would be ambiguous. But it would work if one of them was LogStep(Delegate).
private void LogStep(Delegate action)
{
var attr = (TestStepAttribute)Attribute
.GetCustomAttribute(action.Method, typeof(TestStepAttribute));
Console.WriteLine("LogStep(Delegate action): " + attr?.Description);
}
private void LogStep(Expression<Action> actionExpr)
{
string descr = null;
var methodCall = actionExpr.Body as MethodCallExpression;
if (methodCall != null) {
var attribs = methodCall.Method.GetCustomAttributes(typeof(TestStepAttribute), true);
if (attribs.Length > 0) {
descr = ((TestStepAttribute)attribs[0]).Description;
}
}
Console.WriteLine("LogStep(Expression<Action> actionExpr): " + descr);
}
Tests:
LogStep(new Action(DoSomething)); // new Action() Is required here. Calls first overlaod.
LogStep(() => DoSomething()); // Calls second overload.
LogStep(() => new object()); // Calls second overload.
Note that you can compile and execute lambda expressions, in case you need to execute the method.
works perfectly, but when I execute it using lambda expression
LogStep(() => DoSomething()) It tells me that there are no attributes
of type TestStepAttribute in that Action.
Well of course won't find any attributes because you are passing a lambda expression which is basically a method and in that method you pass your method DoSomething() and the check is done on the lambda expression.
Lambda expression is just another method. When you look at action.Method, that's the method you get (and action.Target will contain a closure, if any).
In the end, all you have is:
void SomeAnonymousMethod()
{
DoSomething();
}
To get to the method actually being called, you'd have to decompile the anonymous method first. And of course, you're probably using the lambda syntax to pass arguments while still working with a paremeter-less action, where it gets even crazier:
class SomeClosure
{
string argument1;
int argument2;
void AnonymousMethod()
{
var data = GetSomeData(argument2);
DoSomething(data, argument1);
}
}
How do you even tell that DoSomething is the method you need metadata of?
There isn't a way around this using lambda expressions. Fortunately, it doesn't seem you actually need that anyway, since you're never calling the argument. Instead of using Action, just use Delegate, and you can pass whatever method you need directly:
void DoSomething(string something, string otherThing)
{
... // Not important
}
void LogStep(Delegate someDelegate)
{
... // Exactly as before
}
LogStep((Action<string, string>)DoSomething);
You do have to manually cast at the invocation, sadly, otherwise the compiler gives you an error; you can keep the same signature for the LogStep method itself, though. Alternatively, you could use a simple T4 template to create multiple overloads of the LogStep method so that you can avoid the explicit cast in your hand-written code.

Confusion with Enumerable.Select in C#

I am new to the C# and .NET world. I am trying to understand the following statement.
var xyz = Enumerable.Repeat(obj, 1).ToList();
var abc =
xyz.Select(xyzobj => new res {
foo = bar,
xyzs = new [] {xyzobj},
}).ToList();
I understand that Select takes in an object and a transformer function and returns a new form of the object. But here, it takes in a lambda expression with an enum value and another object.
I am little confused. Is the statement above similar to
var abc = xyz.Select(xyzobj => {
//some work with xyzobj
//and return object.
}).ToList();
Can somebody explain the above statement actually does, my head just spins around with these statements all around in my new work location.
Can somebody direct me to good resources to understand lambda expressions and Enumeration.
There are two main types of lambda expressions in C#.
Expression lambdas like this:
x => foo(x);
This takes a parameter x, and performs some transformation on it, foo, returning the result of foo(x) (though technically it may not return a value of the result type of foo(x) is void).
Statement lambdas look like this:
x => {
// code block
}
This takes a parameter, x and performs some action on it, (optionally returning a value if an explicit return is provided). The code block may be composed of multiple statements, meaning you can declare variables, execute loops, etc. This is not supported in the simpler expression lambda syntax. But it's just another type of lambda.
If it helps you can think of the following as being equivalent (although they are not perfectly equivalent if you are trying to parse this as an Expression):
x => foo(x);
x => { return foo(x); }
Further Reading
Lambda Expressions (C# Programming Guide)
// Creates a IEnumerable<T> of the type of obj with 1 element and converts it to a List
var xyz = Enumerable.Repeat(obj, 1).ToList();
// Select takes each element in the List xyz
// and passes it to the lambda as the parameter xyzobj.
// Each element is used to create a new res object with object initialization.
// The res object has two properties, foo and xyzs. foo is given the value bar
// (which was defined elsewhere).
// The xyzs property is created using the element from xyz passed into the lambda
var abc = xyz.Select(
xyzobj => new res {
foo = bar,
xyzs = new [] {xyzobj},
}).ToList();

Pass Expression Tree as Method parameter

I have a function:
public void Execute(Expression<Action> expression)
{
var time = expression.Compile().Benchmark();
var msg = string.Format("{0} took {1} to complete",
ReflectionHelper.GetComponentCallDetails().ToString(),
time.ToString(#"hh\:mm\:ss\.ff"));
Logger.Info(msg);
}
The delegate that needs to be called is something like:
channels = GetAllChannelsImpl(maxResults);
I am relatively new to Expression Trees and cannot figure out a way to pass the Action delegate to the method.
I was able to do the same functionality using
public void Execute(Action action)
{
var time = action.Benchmark();
var msg = string.Format("{0} took {1} to complete",
ReflectionHelper.GetComponentCallDetails().ToString(),
time.ToString(#"hh\:mm\:ss\.ff"));
Logger.Info(msg);
}
and calling as
Execute(() =>
{
channels = GetAllChannelsImpl(maxResults);
});
But I wanted to use the Expression Tree based approach in order to eliminate the need to use the overhead of reflection to figure out the details of the method invoked to log it.
Can anyone suggest the right way to pass the expression tree for the above action delegate as a method parameter.
A lambda expression by itself does not have a type. The actual type it takes is inferred by the compiler depending on what you are trying to assign or cast to. With that said, any calls to your Execute() method using simple lambdas will be ambiguous since your lambda would be compatible as an Action or Expression<Action>. You would have to disambiguate this by explicitly casting to the type you expect.
// assign to a variable
Expression<Action> action1 = () => ...;
Execute(action1);
// cast
Execute((Expression<Action>)(() => ...));
// use the constructor
Execute(new Expression<Action>(() => ...));
It would be better IMHO to remove the ambiguous overload and rename one of the methods. I'd recommend renaming the expression overload to ExecuteExpression().

Is there a delegate that combines the functionality of Func<T> and Action<T>?

When you call a Action<T> you will pass in a variable of type T which will be available to the code defined in the delegate, e.g.
var myAction = new Action<string>(param =>
{
Console.WriteLine("This is my param: '{0}'.", param);
});
myAction("Foo");
// Outputs: This is my param: 'Foo'.
And when you call a Func<T> the delegate will return a variable of type T, e.g.
var myFunc = new Func<string>(() =>
{
return "Bar";
});
Console.WriteLine("This was returned from myFunc: '{0}'.", myFunc());
// Outputs: This was returned from myFunc: 'Bar'.
Here's the question -
Is there a third delegate type which will take an input parameter and also return a value? Something like -
var fooDeletegate = new FooDelegate<string, int>(theInputInt =>
{
return "The Answer to the Ultimate Question of Life, the Universe, and Everything is " + theInputInt;
});
Console.WriteLine(fooDeletegate(42));
// Outputs: The Answer to the Ultimate Question of Life, the Universe, and Everything is 42
If such a thing doesn't exist, would it possible to use Action<Func<sting>> for this sort of functionality?
You're looking for Func<T, TResult>, or one of its 15 other overloads.
There are Func<> overloads with [more than zero] parameters Func<TParam, TReturn>, Func<TParam1, TParam2, TReturn>, etc.
you can do this with new Func<inputType1, inputType2, inputType3, outputType>(). This is possible with 0 to 16 input parameters. You will find the different Func overloads in the System namespace.

Categories