How does Select(int.Parse) work in such Linq expression?
"1,2,3,4,5".Split(',').Select(int.Parse).ToList(); //ok
"1,2,3,4,5".Split(',').Select(x => int.Parse(x)).ToList(); //ok
Why example with Console.Writeline returns compilation error?
"1,2,3,4,5".Split(',').Select(Console.WriteLine).ToList(); //error
"1,2,3,4,5".Split(',').Select(x => Console.WriteLine(x)).ToList(); //ok
When it is allowed to omit lambda like (x => ....(x))
Console.WriteLine as well as int.Parse are so-called method groups. Groups of methods. Because of the various overloads of those methods. It can be exactly one method, or multiple methods.
A method group can be converted to a delegate if the compiler can infer which method of the group is meant. For example the method group int.Parse can be a delegate to int.Parse(string) if a Func<string, int>is expected.
This works in your first example. Select expects a Func<T, T2> and your T is already set to be of type string. However, it does not work with your second example. Because while Console.WriteLine is a method group, not a single method in this group corresponds to the required Func<T, T2> because the return type of all of the methods in the group is void.
The signature of Select looks somewhat like this:
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector);
So for the selector a method (or lambda) with the signature
TResult Method(string s);
is expected. Console.WriteLine() is of return type void which is not a valid type for TResult. So in fact both lines:
"1,2,3,4,5".Split(',').Select(Console.WriteLine).ToList();
"1,2,3,4,5".Split(',').Select(x => Console.WriteLine(x)).ToList();
don't compile. Are you sure you really compiled that second line? My compiler raises error CS0411 for both lines.
Select is a projections statement, it transforms your object into a new object that you specify inside the Select.You need to loop and execute the WriteLine:
"1,2,3,4,5".Split(',').ToList().ForEach(x=> { Console.WriteLine(x); });
Select expects a parameter Func<char, T>, Console.WriteLine doesn't match that.
Almost all LINQ extensions accept a function that returns a value. Console.WriteLine does not return anything, so it can't be used as parameter.
"12345".Select(x => { Console.WriteLine(x); return x; }).ToList(); // this will work
"12345".Select(int.TryParse).ToList(); // this will NOT work because TryParse needs more than one parameter
"12345".ToList().ForEach(Console.WriteLine); // this will work because .ForEach accepts a method that does not return anything (void)
"12345".ToList().ForEach(int.Parse); // this will NOT work
It's allowed when the method signature is the same as LinQ expects.
In your first case, the Select's expected signature a method with one string parameter and return value of int (or simply Func<string, int>) and int.Parse method has the same signature, that's why it's working;
while in the second case, the Console.WriteLine's signature is a method with one string parameter and no return value (or return value of special type void) (or simply Action<string>), and hence signature that Select expects and signature that Console.WriteLine has do not match.
Related
Could you please explain what this strange code does?
expression.Compile()();
Why are there 2 pairs of parentheses here? I didn't find anything in google. The full method is
public Validator NotEmpty(Expression<Func<IEnumerable<T>>> expression)
{
var member = (MemberExpression)expression.Body;
string propertyName = member.Member.Name;
IEnumerable<T> value = expression.Compile()();
if (value == null || !value.Any())
{
ValidationResult.AddError(propertyName, "Shouldn't be empty");
}
return this;
}
It is used like this:
_validator.NotEmpty(() => request.PersonIds); // request.PersonIds is List<int>
This method checks if a collection is empty or null. Everything works fine but I am a little bit confused with that code. I have never seen using 2 pairs of parentheses before in C#. What does it mean?
Well, you pass list of int into the method as expression tree. This expression produces the value of IEnumerable<T> (in this case IEnumerable<int>).
To get value of expression you need to compile this expression into a delegate Func<IEnumerable<T>> and then invoke the delegate.
In fact, I can write two separate lines of code instead of the shorter syntax used above:
Func<IEnumerable<T>> del = expression.Compile();
IEnumerable<T> value = del();
The two brackets () is actually an operator which invokes a method or delegate. See here.
The expression "expression.Compile()" seems to deliver a delegate that can be invoked. The second pair of brackets then invokes this delegate.
You could also rewrite this as:
var del = expression.Compile();
del();
I found a little script that I understand fully. I've got a string with "1 -2 5 40" for example. It reads the input string, splits it into a temporary array. Then this array is parsed and each element is transformed into an integer. The whole thing is order to give the nearest integer to zero.
But what I don't understand is the notation Select(int.Parse). There is no lambda expression here and the method int.Parse isn't called with brackets. Same with the OrderBy(Math.Abs)
Thank you in advance =)
var temps = Console.ReadLine().Split(new []{' '}, StringSplitOptions.RemoveEmptyEntries);
var result = temps.Select(int.Parse)
.OrderBy(Math.Abs)
.ThenByDescending(x => x)
.FirstOrDefault();
int.Parse is a method group - what you're seeing is a method group conversion to a delegate. To see it without LINQ:
Func<string, int> parser = int.Parse;
int x = parser("10"); // x=10
It's mostly equivalent to:
Func<string, int> parser = text => int.Parse(text);
... although there are plenty of differences if you want to go into the details :)
Select(int.Parse) is nearly equivalent to Select(x => int.Parse(x)).
The Select demands an Func<T, R>, which in this case is also the signature of int.Parse (it has a single parameter with a return value). It convers the method group to the matching delegate.
In this case Func<T, R> will map to Func<string, int>, so it matches the int Parse(string) signature.
int.Parse is a method with signature string -> int (or actually, a method group, with different signatures. But the compiler can infer you need this one, because it is the only one that fits.
You could use this method as a parameter wherever you would supply a delegate parameter with the same signature.
The parameter for .Select() is Func<T1, T2>() where T1 is the input parameter (the individual values of temps), and T2 is the return type.
Typically, this is written as a lambda function: x => return x + 1, etc. However, any method that fits the generic definitions can be used without having to be written as a lambda since the method name is the same as assigning the lambda to a variable.
So Func<string, int> parseInt = s => Convert.ToInt32(s); is syntactically equivalent to calling the method int.Parse(s).
The language creates the shortcut of automatically passing the Func parameter to the inside method to create more readable code.
Select LINQ IEnumerable<> extension method signature looks like that:
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector
)
Look at the selector argument. In your case you pass to Select .Net standard function int.Parse which has signature:
public static int Parse(
string s
)
.Net compiler can convert delegates to Func<...> or Action<...>. In case of int.Parse it can be converted to Func and therefore can be passed as argument to Select method.
Exactly the same with OrderBy. Look at its signature too.
Say I have the following method:
static int MethodWithDefaultParameters(int a, int b=0, int c=1)
{
return a + b + c;
}
And then I use this method in a LINQ query like so:
Enumerable.Range(1,10).Select(MethodWithDefaultParameters);
This fails with:
Error 1 The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Of course, I can work around this by inserting a lambda that forwards the function call like this:
Enumerable.Range(1,10).Select(i => MethodWithDefaultParameters(i));
But my question is why does the type inference fail? As far as I can tell, it should not be ambiguous as there is only one variant of the function that satisfies the input variable.
There are two overloads for Select(). One that takes as the second parameter (i.e. the delegate) a Func<TSource, TResult>, and one that takes a Func<TSource, int, TResult>. I.e. a method signature with either one parameter or two.
Your method satisfies neither. Even with the default values, it still has three parameters. Default parameters are a compile-time construct and must be provided at the call site. They aren't filled in at run-time via a call to a delegate instance.
So, in fact, your work-around is one of the two reasonable ways to address the problem. The other would be to implement the default parameters differently (i.e. "old-school" :) ):
static int MethodWithDefaultParameters(int a)
{
return MethodWithDefaultParameters(a, 0, 1);
}
static int MethodWithDefaultParameters(int a, int b, int c)
{
return a + b + c;
}
Then you can use MethodWithDefaultParameters in your call to Select() directly, as the compiler will find the single-parameter overload that is compatible with one of the Select() overloads.
There's a similar question here:
Pass Method as Parameter using C#
Which assumes you know the method's arguments and return type. I'd like to do something a bit different. I'm looking to create a version of System.Reflection's .GetMethod(string) that instead takes a lambda function - so instead of:
MethodInfo methodInfo = typeof(MyClass).GetMethod("AddThing");
I could use a more compile-safe:
MethodInfo methodInfo = ReflectionHelper.GetMethod<MyClass>(mc => mc.AddThing);
So if ReflectionHelper knew the argument count and return type beforehand the answer would be simple-ish - for example if it had no arguments and returned string:
public static MethodInfo GetMethod<T, TReturn>(Expression<Func<T, Func<TArg, TReturn>>> expr)
{
return ((MethodCallExpression)expr.Body).Method;
}
Except that I don't know the argument count/return type beforehand, and I'd like to avoid just spamming it with 20 overloads that cover most but not all cases.
So, how do I do this?
You haven't specified a method in the lambda mc => mc.AddThing - you've specified a method group.
What you could do is write a method call in the expression - although it will never be executed, so the parameters just have to specify the overload you want.
So, to use it, you would write:
MethodInfo mi = GetMethod<MyClass>( mc => mc.AddThing( null ) );
Then the expression could just be an Action, not a Func:
public static MethodInfo<T>( Expression<Action<T>> expr )
{
return ( ( MethodCallExpression ) x.Body ).Method;
}
As always with expression inspection, this is prone to runtime errors if the lambda isn't of the expected form, but it's a step in the right direction to get rid of "magic" strings.
The workaround I'm using for now, that I'll call "the spam approach," is ugly but functional in a limited set of scenarios:
public class ReflectionHelper<T>
{
public MethodInfo GetMethod<TA1>(Expression<Func<T, Func<TA1>>> expr)
{
return ((MethodCallExpression)expr.Body).Method;
}
public MethodInfo GetMethod<TA1, TA2>(Expression<Func<T, Action<TA1, TA2>>> expr)
{
return ((MethodCallExpression)expr.Body).Method;
}
public MethodInfo GetMethod<TA1, TA2, TA3>(Expression<Func<T, Action<TA1, TA2, TA3>>> expr)
{
return ((MethodCallExpression)expr.Body).Method;
}
. . . // And more
}
And it goes on, to specify a long list of potential Actions and Funcs with various argument counts. This allows me to in fact use it like:
(new ReflectionHelper<MyClass>()).GetMethod<string>(mc => mc.SaySomething).Invoke("Hi");
So it's close-ish - I get to just call the method by name, and I do avoid passing fake arguments in order to do so, but I still get caught up laying out what the Types of its arguments are - more complex than I hoped for. In a situation with multiple method overloads of the same name, passing the types of the arguments would however narrow the method list down to one specific overload.
I'd still be interested in something even simpler that can just take a method as in my Question however. It would be vague in method overload situations, but so is the standard .GetMethod(string).
This is a question about the SYNTAX of c# and NOT about how we call/use IQueryable
Can someone please explain to me:
We have this declaration (System.Linq):
public static double Average<TSource>(this IQueryable<TSource> source,
Expression<Func<TSource, int>> selector)
and to call the Average
double average = fruits.AsQueryable().Average(s => s.Length);
I understand how to call the Average and all the similar static method of IQueryable
but I don’t understand the syntax of the declaration.
public static double Average<TSource>(this IQueryable<TSource> source,
Expression<Func<TSource, int>> selector)
What does the <TSource> mean in Average<TSource>(
and also the this IQueryable<TSource> source.
since only one parameter passes when we call it and the actual lambda expression (s => s.Length);
Thanks in advance.
The <TSource> part declares the generic type parameters of the method - basically what kind of element the sequence contains. You should definitely understand generics before you get too far into LINQ.
Then,
this IQueryable<TSource> source
indicates the first parameter of the method:
this indicates that it's an extension method
IQueryable<TSource> indicates the type of the parameter
source is the name of the parameter
The fact that it's an extension method is probably what's confusing you. When you call
query.Average(s => s.Length)
that is converted by the compiler into
Queryable.Average(query, s => s.Length)
You're declaring an extension method (that's the this keyword) that adds your method to any type implementing IQueryable<TSource> where TSource is the generic type, and remains the same throughout the expression.
The compiler can infer the generic type in this case, so you don't need to declare it when calling the method
TSource is the generic type that you will declare. It's basically what type the s is.
Average<TSource> because this is a Generic Method. The method can be run on a query or enumeration over any type (as long as a suitable selector for that type is provided).
this IQueryable<TSource> source because this is an Extension Method. Extension methods allow you to add additional methods to existing types without having to alter that type's definition. In this case Linq adds the Average method to the IQueryable interface without altering that interface.
<TSource> is a generic Parameter of the method.
this IQueryable<TSource> source denotes an extension method, this is syntactic sugar. In C#2.0, it would simply be a static method you'd have to call explicitly, with this, the compiler allows you to call it as if it was a member of the Type you are calling it on.
<X> is used to make generic functions that work with different types.
X add<X>(X a, X b){return a + b;}
int a = 1;
int b = 2;
int c = add<int>(a,b);
string d = "hello ";
string e = "world";
string f = add<string>(c,d);
this is a keyword for extensions methods:
string putinsidestars(this string x){
return "*" + x + "*";
}
string foo = "bar";
string z = foo.putinsidestars();
// z now contains *bar*