c# syntax and Linq, IQueryable - c#

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*

Related

Returning different type via generics in C#

My generic extension method signature:
public static class MyExtensions
{
public static IEnumerable<R> DoThing<T, R>(this IEnumerable<T> source)
where T : class
where R : class
{
throw new NotImplementedException();
}
}
My usage pattern:
List<MyItem> codes = new List<MyItem>();
List<MyNewItem> newValues = codes.Where(o => o.Property== 1).DoThing<MyItem, MyNewItem>();
codes.Where should result in an IQueryable< T > output, it's the normal System.Linq namespace.
Results in:
'IEnumerable' does not contain a definition for 'DoThing' and no extension method 'DoThing' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)
I needed to specify both Types, T and R, as it turns out.
Thank you, all for the help!
you must either specify no Types or all of them
do this
List<MyNewItem> newValues = codes.Where(o => o.Property== 1).DoThing();
that wont work with the code you show (cos it doesnt return anything) but if you fix it it probably will. Else do this
List<MyNewItem> newValues = codes.Where(o => o.Property== 1).DoThing<MyNewItem, MyItem>();
You cannot do partial method type inference in C#. It would be nice if you could, but you can't. Your choices are to either provide the entire list of type arguments for the method call, or none of them and have them deduced.
In your case type inference will never deduce the type of R because type inference only looks at arguments and formals and there is no formal that uses R.
Looking more specifically at your scenario: I cannot for the life of me see what the body of your method could possibly be; it must create a sequence of R out of a sequence of T. OK, let's suppose T is Giraffe and R is Comparer<Nullable<Rectangle>>. How on earth are you going to get a bunch of nullable rectangle comparers out of a bunch of giraffes?
You are almost certainly doing something very wrong here. Typically you would provide a function to do that. That's why the signature of Select is
public static IEnumerable<R> Select<A, R>(
this IEnumerable<A> items,
Func<A, R> projection)
Now there is enough compile time information for the compiler to deduce both A and R from the call site arguments, and there is a way to get a sequence of R out of a sequence of A, by calling the projection on each A.

C# notation understanding Select(int.Parse)

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.

C# Linq and lambda

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.

C# Type Inference fails with methods that contain default parameters

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.

Why can't an anonymous method be assigned to var?

I have the following code:
Func<string, bool> comparer = delegate(string value) {
return value != "0";
};
However, the following does not compile:
var comparer = delegate(string value) {
return value != "0";
};
Why can't the compiler figure out it is a Func<string, bool>? It takes one string parameter, and returns a boolean. Instead, it gives me the error:
Cannot assign anonymous method to an
implicitly-typed local variable.
I have one guess and that is if the var version compiled, it would lack consistency if I had the following:
var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
return false;
};
The above wouldn't make sense since Func<> allows only up to 4 arguments (in .NET 3.5, which is what I am using). Perhaps someone could clarify the problem. Thanks.
UPDATE: This answer was written over ten years ago and should be considered to be of historical interest; in C# 10 the compiler will infer some delegate types.
Others have already pointed out that there are infinitely many possible delegate types that you could have meant; what is so special about Func that it deserves to be the default instead of Predicate or Action or any other possibility? And, for lambdas, why is it obvious that the intention is to choose the delegate form, rather than the expression tree form?
But we could say that Func is special, and that the inferred type of a lambda or anonymous method is Func of something. We'd still have all kinds of problems. What types would you like to be inferred for the following cases?
var x1 = (ref int y)=>123;
There is no Func<T> type that takes a ref anything.
var x2 = y=>123;
We don't know the type of the formal parameter, though we do know the return. (Or do we? Is the return int? long? short? byte?)
var x3 = (int y)=>null;
We don't know the return type, but it can't be void. The return type could be any reference type or any nullable value type.
var x4 = (int y)=>{ throw new Exception(); }
Again, we don't know the return type, and this time it can be void.
var x5 = (int y)=> q += y;
Is that intended to be a void-returning statement lambda or something that returns the value that was assigned to q? Both are legal; which should we choose?
Now, you might say, well, just don't support any of those features. Just support "normal" cases where the types can be worked out. That doesn't help. How does that make my life easier? If the feature works sometimes and fails sometimes then I still have to write the code to detect all of those failure situations and give a meaningful error message for each. We still have to specify all that behaviour, document it, write tests for it, and so on. This is a very expensive feature that saves the user maybe half a dozen keystrokes. We have better ways to add value to the language than spending a lot of time writing test cases for a feature that doesn't work half the time and doesn't provide hardly any benefit in cases where it does work.
The situation where it is actually useful is:
var xAnon = (int y)=>new { Y = y };
because there is no "speakable" type for that thing. But we have this problem all the time, and we just use method type inference to deduce the type:
Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });
and now method type inference works out what the func type is.
Only Eric Lippert knows for sure, but I think it's because the signature of the delegate type doesn't uniquely determine the type.
Consider your example:
var comparer = delegate(string value) { return value != "0"; };
Here are two possible inferences for what the var should be:
Predicate<string> comparer = delegate(string value) { return value != "0"; }; // okay
Func<string, bool> comparer = delegate(string value) { return value != "0"; }; // also okay
Which one should the compiler infer? There's no good reason to choose one or the other. And although a Predicate<T> is functionally equivalent to a Func<T, bool>, they are still different types at the level of the .NET type system. The compiler therefore cannot unambiguously resolve the delegate type, and must fail the type inference.
Eric Lippert has an old post about it where he says
And in fact the C# 2.0 specification
calls this out. Method group
expressions and anonymous method
expressions are typeless expressions
in C# 2.0, and lambda expressions join
them in C# 3.0. Therefore it is
illegal for them to appear "naked" on
the right hand side of an implicit
declaration.
Different delegates are considered different types. e.g., Action is different than MethodInvoker, and an instance of Action can't be assigned to a variable of type MethodInvoker.
So, given an anonymous delegate (or lambda) like () => {}, is it an Action or a MethodInvoker? The compiler can't tell.
Similarly, if I declare a delegate type taking a string argument and returning a bool, how would the compiler know you really wanted a Func<string, bool> instead of my delegate type? It can't infer the delegate type.
The following points are from the MSDN regarding Implicitly Typed Local Variables:
var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement.
It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type.
MSDN Reference: Implicitly Typed Local Variables
Considering the following regarding Anonymous Methods:
Anonymous methods enable you to omit the parameter list.
MSDN Reference: Anonymous Methods
I would suspect that since the anonymous method may actually have different method signatures, the compiler is unable to properly infer what the most appropriate type to assign would be.
My post doesn't answer the actual question, but it does answer the underlying question of :
"How do I avoid having to type out some fugly type like Func<string, string, int, CustomInputType, bool, ReturnType>?" [1]
Being the lazy/hacky programmer that I am, I experimented with using Func<dynamic, object> - which takes a single input parameter and returns an object.
For multiple arguments, you can use it like so:
dynamic myParams = new ExpandoObject();
myParams.arg0 = "whatever";
myParams.arg1 = 3;
Func<dynamic, object> y = (dynObj) =>
{
return dynObj.arg0.ToUpper() + (dynObj.arg1 * 45); //screw type casting, amirite?
};
Console.WriteLine(y(myParams));
Tip: You can use Action<dynamic> if you don't need to return an object.
Yeah I know it probably goes against your programming principles, but this makes sense to me and probably some Python coders.
I'm pretty novice at delegates... just wanted to share what I learned.
[1] This assumes that you aren't calling a method that requires a predefined Func as a parameter, in which case, you'll have to type that fugly string :/
Other answers were correct at the time they were written, but starting from C# 10.0 (from 2021), the compiler can infer a suitable delegate type (like some Func<...>, Action<...> or generated delegate type) in such cases.
See C# 10 Features - Lambda improvements.
var comparer = delegate(string value) {
return value != "0";
}; // OK in C# 10.0, picks 'Func<string, bool>' in this case
Of course the more usual syntax is to us =>, so:
var comparer = (string value) => {
return value != "0";
}; // OK in C# 10.0, picks 'Func<string, bool>' in this case
How is about that?
var item = new
{
toolisn = 100,
LangId = "ENG",
toolPath = (Func<int, string, string>) delegate(int toolisn, string LangId)
{
var path = "/Content/Tool_" + toolisn + "_" + LangId + "/story.html";
return File.Exists(Server.MapPath(path)) ? "<a style=\"vertical-align:super\" href=\"" + path + "\" target=\"_blank\">execute example</a> " : "";
}
};
string result = item.toolPath(item.toolisn, item.LangId);

Categories

Resources