Please help me with Queryable.select - c#

How can I fix this error ?
> Type arguments for method Queryable.Select<TSource>,<TResult> ....
> cannot be inferred from the usage.
> Try specifying the type arguments explicitly.
This is my code
Comments = e.Comments.AsQueryable().Select(CommentViewMode.ViewModel)
It shows the red squiggly line on 'Select'

Minnie,
The LINQ Select extension method for IQueryable takes a function as an argument. The documentation from Microsoft shows the signature and a simple example:
List<int> range =
new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Project the square of each int value.
IEnumerable<int> squares =
range.AsQueryable().Select(x => x * x);
So the Select method expects a function that takes an argument of the same type as your queryable enumerates. In the example above, it is an int. In the code you provided it will be the type of one of your Comments elements. I expect you need to write your select like this:
var something = e.Comments.AsQueryable().Select(x => x.SomePropertyOfYourCommentClass)

Related

C# Sort, cannot convert lambda expression to System.Array

Based on what I've found on .Sort() this should work
using System;
using System.Linq;
public class Test
{
public static void Main()
{
int[] test = new int[] {6, 2, 1, 4, 9, 3, 7};
test.Sort((a,b) => a<b);
}
}
However, I'm getting this error message:
error CS1660: Cannot convert `lambda expression' to non-delegate type `System.Array'
That's the simplest version I could find to get that error. In my case, I'm taking a string, giving it a complex ranking value, and comparing that.
What am I missing here?
The overload of Sort that you are after expects a delegate that takes in two objects of the type contained within the array, and returns an int. You need to change your expression to return an int, where you return a negative value for items that come before the other, zero when the items are "equal", and a positive value for items that come after the other.
Also, for arrays the Sort method is static, so you call it using the class name, not as an instance:
Array.Sort(test, (left, right) => left.CompareTo(right));
CompareTo is a built-in function on types that are IComparable (like int), and it returns an int in the manner I described above, so it is convenient to use for sorting.

Confused as to why this C# code compiles, while similar code does not

Let's take the following extension method:
static class Extensions
{
public static bool In<T>(this T t, params T[] values)
{
return false;
}
}
I'm curious as to why this code compiles and runs:
var x = new Object();
IEnumerable<int> p = new List<int> { 1, 2, 3 };
var t2 = x.In(p);
Within In, values is an Object[], as if the List<int> gets converted on the fly to an array. To me, it seems that params T[] does not match IEnumerable<int>, which is why I'm surprised this even runs.
Now this code:
var x = 5;
IEnumerable<int> p = new List<int> { 1, 2, 3 };
var t2 = x.In(p);
Does not run and generates the compiler error:
Error 2 Argument 2: cannot convert from
'System.Collections.Generic.IEnumerable' to 'int[]'
This is what I'd expect from the first one actually. Can someone explain what's going on here? Thanks!
Type inference converts your first call to
In<object>(x, p);
The parameters of this closed generic method are object, params object[].
Therefore, passing p implicitly converts it to an object, which becomes the single item in the params array.
Your second call is inferred (because of the first parameter) to
In<int>(x, p);
Here, the second parameter can either be an int[] (passing an array directly) or a series of ints (via params).
Since IEnumerable<int> is neither of those, you get an error.

C# List Generic Extension Method vs Non-Generic

This is a simple question (I hope), there are generic and non-generic methods in collection classes like List<T> that have methods such as Where and Where<T>.
Example:
List<int> numbers = new List<int>()
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
IEnumerable<int> evens = numbers.Where((x) =>
{
return x % 2 == 0;
});
IEnumerable<int> evens2 = numbers.Where<int>((x) =>
{
return x % 2 == 0;
});
Why use one over the other (Generic or Non-Generic)?
They're the same method (documentation here). The type parameter portion after the method name (i.e. <int> in this case) is optional when the compiler is able to infer the type automatically and unambiguously from context. In this case, the method is being applied to an object implementing the interface IEnumerable<int> (i.e. the object numbers of type List<int>) from which the compiler can safely infer that the type parameter is int.
Note, also, that Where<T> is actually an extension method on the System.Linq.Enumerable class which can be applied to objects of any class implementing IEnumerable<T> such as List<T>.

How to cast a GroupedEnumerable?

I am playing about with the IQueryProvider.Execute command and am passing in an expression which is part of my expression tree project. This command gives me back an object which can be either an OrderedEnumerable or a GroupedEnumerable depending on the original expression. A GroupBy expression creates the GroupedEnumerable object. The following code also creates a GroupedEnumerable object which will show you an example of the problem I am having.
List<int> numbers = new List<int> { 1, 7, 16, 23, 41, 66 };
object grouped = numbers.GroupBy(n => n % 2 == 0);
When “grouped” is an object (of GroupedEnumerable) I cannot cast it to any other type that will allow me to call “GetEnumerator” on it. I am also unable to cast it to anything that will allow me to use it with a “foreach” command for example. If I change the code to use a “var” (as shown below), grouped is now of type OrderedEnumerable. I can get the enumerator and use it in a foreach command.
List<int> numbers = new List<int> { 1, 7, 16, 23, 41, 66 };
var grouped = numbers.GroupBy(n => n % 2 == 0);
Going back to my expression tree project, the IQueryProvider.Execute command returns an object but I need to be able to cast the object to an OrderedEnumerable when the object is a GroupedEnumerable. All the casts I have tried show an error along the lines of “Unable to cast object of type 'System.Linq.GroupedEnumerable`3 to type .....”. Anyone able to tell me how to cast the object to something more useful?
The result of your GroupBy call will be IEnumerable<IGrouping<bool, int>>. You can see this if you hover over the word var in your second code example. Cast it to this type and it will work correctly.
List<int> numbers = new List<int> { 1, 7, 16, 23, 41, 66 };
object grouped = numbers.GroupBy(n => n % 2 == 0);
IEnumerable<IGrouping<bool, int>> foo =
(IEnumerable<IGrouping<bool, int>>)grouped;
Edit
After your comments above, if the output of your call is GroupedEnumerable<MyEntityItem,int?,MyEntityItem>, then you can cast it to IEnumerable<IGrouping<int?, MyEntityItem>>.
Just cast the object to IEnumerable<T>. The enumerable implementation shouldn't matter to you.

What is actually happening with IQueryable.Where()?

This is is returning a boolean based on whether or not there are some matching IDs.
from t in getAll
select new Result
{
...
bool DetailsAvailable =
(db.SaveTrackings.Where(s => s.BundleID == t.bundleID
&& s.UserID == t.userID)
.Count() > 0) ? true : false;
}
This is what I think understand: .Where() is returning all the entries with the matching IDs and then the .Count() is just seeing how many are there. I only feel like I half understand what we need s for.
I know what to expect from this code since it's been in use I just don't understand how it works and some of the documentation from MSDN is using some terminology that is confusing me.
All lambda expressions use the lambda
operator =>, which is read as "goes
to". The left side of the lambda
operator specifies the input
parameters (if any) and the right side
holds the expression or statement
block. The lambda expression x => x *
x is read "x goes to x times x."
So how am I suppose to understand what my code means based on this, .Where(s "goes to" s.BundleID == t.BundleID...) so what's happening here? What does "goes to" mean? Is it comparing every ID in s to everyone one available in t? How do I understand why it's called "goes to" and what exactly is happening?
And then it gets more confusing...
The => operator has the same
precedence as assignment (=) and is
right-associative.
Lambdas are used in method-based LINQ
queries as arguments to standard query
operator methods such as Where.
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.
What is a delegate type System.Func<T, TResult> and how is it created with this "goes to" operator?
I can't just use code because I know that it's working, I need to understand how/why.
Maybe it would help to see this function implemented by hand:
using System;
using System.Collections.Generic;
namespace CSharpSandbox
{
class Program
{
static IEnumerable<T> Where<T>(IEnumerable<T> input, Func<T, bool> predicate)
{
foreach (T item in input)
{
if (predicate(item))
yield return item;
}
}
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> evens = Where(numbers, n => n % 2 == 0);
foreach (int even in evens)
{
Console.WriteLine(even);
}
}
}
}
The construct name => someEvaluation creates an anonymous function consisting of the following parts:
name is simply the name of a parameter, its type is inferred from its usage. You need a name so you can refer to the argument passed in the function.
=> is the start of your anonymous functions body, the scope of the body is a single expression.
someEvaluation is the body of your anonymous function composed of a single expression.
In our case, Func<T, bool> defines a function which takes a single parameter of type T and returns an output of type bool. (If we had used Func<T, U, bool>, we'd take two inputs of type T and U and return a bool. The last type parameter in the Func definition is the return value.)
You can invoke an instance of Func exactly as you invoke any other function. If the func takes params, you pass them in as expected, your parameters are bound to the variable names you defined. When you invoke the function, control flow will jump inside your function and evaluate its results.
In principle, you don't need to create a Func anonymously. You can pass in any function which has a compatible type signature, such as:
static bool IsEven(int n)
{
return n % 2 == 0;
}
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> evens = Where(numbers, IsEven);
foreach (int even in evens)
{
Console.WriteLine(even);
}
}
This program produces the same output. In fact, behind the scenes, the syntax name => expression is syntax sugar; when it gets compiled, C# will produce a produce a private function with a hidden name and convert it to the format above.
If it helps, think of s as a variable of type SaveTracking. It's iterating over each s in your collection/table, and testing the value of its BundleID.
The t is same idea - it's like it's iterating through all the return collection from the getAll.
It's like the SQL pseudocode:
SELECT * FROM SaveTracking INNER JOIN GetAll
ON BundleID AND UserID
For a deeper technical description of what's going on with lambda expressions, check out Jon Skeet's book C# In Depth. Chapter 9 , p 230. I found this book very helpful.
Lambda expressions are just a way to shorten the code but it does exactly the same things as declaring a method that corresponds to the delegate type System.Func<T, TResult>
I believe that C# converts your lamba to a method in the background when you compile and it looks like this :
bool LambdaExpression(YourType s)
{
return s.BundleID == t.bundleID && s.UserID == t.userID;
}

Categories

Resources