Two candidates in method Enumerable.Where - c#

Has anyone encountered this problem? I have two same candidates to method Enumerable.Where
And what is the Func'2 and Func'3?
When i trying to filter enumerable
var subItems = itemsToShow.Where(item => item.Visible);
I have an error:
Cannot resolve method 'Where(lambda expression)', candidates are
System.Collection.Generic.IEnumerable<T> Where<T>(this System.Collection.Generic.IEnumerable<T>, System.Func'2) (in calss Enumerable)
System.Collection.Generic.IEnumerable<T> Where<T>(this System.Collection.Generic.IEnumerable<T>, System.Func'3) (in calss Enumerable)
On .Net 3.5 this work perfect

A quick look at the MSDN tells you that there are in fact two overloads.
One just filters based on a predicate, and the second overload also takes the index of the item in the enumeration into account.

Func'3 and Func'2 meens that it is a generic class with 2 and 3 type parameters.
I assume that first is for Func<T, bool> where T is your earlier defined type.
and Func<T, int, bool> the same plus indexer.
Func<T, int, bool> - it is a predicate that accepts two arguments of types T and int and returns bool.

Just build the solution and see the detailed error. Mine was a nullable boolean.

It happened to me because I was trying to use .Contains on a List type, while what I needed was .Any
for example
var myObjectsList = new List<MyClass>();
// instead of this
myObjectList.Contains(x => x.Id == 1)
// use this
myObjectList.Any(x => x.Id == 1)

Try casting to an IQueryable. Like so: itemsToShow.AsQueryable()

Related

Why does IEnumerable's Where pass first argument as "this"

I've just started to study on LINQ. The following example uses Where which is one of the standard query operators.
string[] names = { "Tom", "Dick", "Harry" };
IEnumerable<string> filteredNames = System.Linq.Enumerable.Where(names, n => n.Length >= 4);
I did some research on how it works and found this source:
public static partial class Enumerable
{
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Where(predicate);
if (source is TSource[]) return new WhereArrayIterator<TSource>((TSource[])source, predicate);
if (source is List<TSource>) return new WhereListIterator<TSource>((List<TSource>)source, predicate);
return new WhereEnumerableIterator<TSource>(source, predicate);
}
/* ... */
}
I don't understand why its first parameter, this IEnumerable<TSource> source, is prefixed with the this keyword. I know that extension methods allow an existing type to be extended with new methods without
altering the definition of the original type and that the type
of the first parameter will be the type that is extended.
Can you explain its logic beneath?
Because it is an Extension Method.
So that instead of
IEnumerable<string> filteredNames = System.Linq.Enumerable.Where(names, n => n.Length >= 4);
You can also use it like:
IEnumerable<string> filteredNames = names.Where(n => n.Length >= 4);
The Reason it is an extension method is that IEnumerable, List, ... existed long before Linq (which was introduced in .Net 3.5) and its job is just to extend finding, filtering, ordering, ... them. So it is logical to have it as an Extention method rather than a separate library. And also consider that this way you can use chaining, which woudln'd be possible if it wasn't an extension:
name.Where(x => x.Length > 4).Select(x => x.Substring(4));
Compare it to:
System.Linq.Enumerable.Select(System.Linq.Enumerable.Where(name, x => x.Length > 4), x => x.Substring(4));
And this is only a very simple one, consider how dirty it gets with larger, complex queries.
Since it's an Extension Method. It means that Where is not a method on IEnumerable but when you reference Linq namespace ,Where method is added to IEnumerable.
for more info read this :
Extension Methods
First of all, The simple answer is because it is an extension method. The definition of extension method is that Their first parameter specifies which type the method operates on, and the parameter is preceded by the this modifier.
Secondly, I disagree Ashkan Mobayen Khiabani's answers last part. you must have a look fluent implementation without extension method.

FindAll - Predicate<TSource> vs Func<TSource, bool>

I am struggling to understand why does not List<T>FindAll(...) method accepts Func<TSource, bool> but instead insists on accepting Predicate<TSource>.
So when I have a List of books and I want to get only books, which are cheaper than 10. This code runs just fine.
Predicate<Book> CheapBooksPredicate = b => b.Price < 10;
var cheapBooksPredicate = books.FindAll(CheapBooksPredicate);
But when I change Predicate<TSource> to Func<TSource, bool>
Func<Book, bool> CheapBooksFunc = b => b.Price < 10;
var cheapBooksFunc = books.FindAll(CheapBooksFunc);
I am getting error:
Argument 1: cannot convert from 'System.Func' to 'System.Predicate'
What Am I missing here ? When both Func<TSource, bool> and Predicate<TSource> are predicates. Predicate<TSource> should be specialized version of a Func that takes and evaluates a value against a set of criteria and returns a boolean, thus I though, that they can replace each other in terms of usage.
They have the same signature, but they are fundamentally different types and cannot be cast as a reference-preserving conversion. Since FindAll wants a Predicate<T>: use Predicate<T>.
Would it be nice if they were castable like this? Maybe, but it would require CLR and language changes, and is unlikely to happen.
You can use the following Extension method to convert Func<T, bool> to Predicate<T>
static Predicate<T> FuncToPredicate<T>(Func<T, bool> func)
{
return new Predicate<T>(func);
}
Reference

What is the purpose of SelectMany(x => x)?

I understand the use of lambda functions as a filter such as (x => x.Count() == 1), but what is the purpose of the (x => x)? When I take it out, the code doesn't compile, and every example of lambda functions I can find seems to use it to filter in one line instead of multiple lines without the lambda.
List<Tuple<int, int>> regVals = ReadRegValCollection.SelectMany(x => x).ToList();
The purpose of this gem is to flatten a List of Lists into a List
x => x is a lambda expression that returns whatever argument it's provided with.
It's equivalent to a method declared as
public T Identity<T>(T item)
{
return item;
}
It's commonly used with SelectMany method to flatten a collection declared as IEnumerable<IEnumerable<T>> into IEnumerable<T>.
SelectMany requires a delegate that matches Func<IEnumerable<TSource>, IEnumerable<TResult>>. In case when a source is IEnumerable<IEnumerable<T>> and you want a result to be IEnumerable<T> no projection has to be done on source collection elements, as they already are IEnumerable<TResult>.

C# Dictionary search predicate as method argument

I am trying to create a function whereby I can pass in a functor/predicate that can slot into a dictionary's 'Where' method.
(cardPool is the dictionary of type 'cardStats')
Pseudo of what I'd like to do:
void CardStats findCard(Predicate<CardStats> pred)
{
return cardPool.Where(pred);
}
This code obviously wont work but is simply a rough example of the functionality I am looking for.
I have had no problems setting this up for lists, but for a Dictionary, its really got me stumped.
Any help would be great, thanks!
Edit:
Ahh sorry I should have mentioned more: Cardstats is the value, the key is of type int. I'd like to sift through the values (cardStats) and test their properties such as ID(int) or name(string).
Dictionary<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>>, so its Where extension method takes a predicate of type Func<KeyValuePair<TKey, TValue>, bool>.
You could implement your method like this:
void CardStats findCard(Func<int, CardStats, bool> pred)
{
return cardPool.Where(kv => pred(kv.Key, kv.Value))
.Select(kv => kv.Value)
.FirstOrDefault();
}
And use it like this:
CardStats stats = myCards.findCard((id, stats) => id == 7);
or
CardStats stats = myCards.findCard((id, stats) => stats.Name == "Ace of Clubs");
Note that using Where on a dictionary doesn't take advantage of the dictionary's quick lookup features and basically treats it as a linear collection of key-value pairs.
One more comment: I would suggest providing a method that returns an IEnumerable of found cards if there are several. Or you could provide one that does that, and one that just returns the first match:
void IEnumerable<CardStats> findCards(Func<int, CardStats, bool> pred)
{
return cardPool.Where(kv => pred(kv.Key, kv.Value))
.Select(kv => kv.Value);
}
void CardStats findCard(Func<int, CardStats, bool> pred)
{
return findCards(pred).FirstOrDefault();
}
I would use FirstOrDefault as the first statement because it will stop as soon it finds a matching element. another thing is that I will consider using something else than a dictionary - because when using it this way is abuse if its indexed purpose.
anyway, this is the code I will use:
public CardStats Find(Func<CardStats, bool> predicate)
{
KeyValuePair<int, Roster> kvCard = cardPool.FirstOrDefault(kvp => predicate(kvp.Value));
if (kvCard.Equals(default(KeyValuePair<int, Roster>)))
return null;
return kvCard.Value;
}

Need help understanding .Select method C#

I am having difficulties understandting what type of statement this is and how to use the .select method.
var lines = System.IO.File.ReadLines(#"c:\temp\mycsvfil3.csv")
.Select(l => new
{
myIdentiafication= int.Parse(l.Split(',')[0].Trim()),
myName= l.Split(',')[1].Trim()
}
).OrderBy(i => i.Id);
any help is appreciated!
The Enumerable.Select method is an extension method for an IEnumerable<T> type. It takes a Func<TSource, TResult> that allows you to take in your IEnumerable<T> items and project them to something else, such as a property of the type, or a new type. It makes heavy use of generic type inference from the compiler to do this without <> everywhere.
In your example, the IEnumerable<T> is the string[] of lines from the file. The Select func creates an anonymous type (also making use of generic type inference) and assigns some properties based on splitting each line l, which is a string from your enumerable.
OrderBy is another IEnumerable<T> extension method and proceeds to return an IEnumerable<T> in the order based on the expression you provide.
T at this point is the anonymous type from the Select with two properties (myIdentiafication and myName), so the OrderBy(i => i.Id) bit won't compile. It can be fixed:
.OrderBy(i => i.myIdentiafication);
This is a LINQ query. Enumerable.Select projects each line from file into anonymous object with properties myIdentiafication and myName. Then you sort sequence of anonymous objects with Enumerable.OrderBy. But you should select property which exists in anonymous object. E.g. myIdentiafication because there is no id property:
var lines = File.ReadLines(#"c:\temp\mycsvfil3.csv") // get sequence of lines
.Select(l => new {
myIdentiafication = int.Parse(l.Split(',')[0].Trim()),
myName= l.Split(',')[1].Trim()
}).OrderBy(i => i.myIdentiafication);
NOTE: To avoid parsing each line twice, you can use query syntax with introducing new range variables:
var lines = from l in File.ReadLines(#"c:\temp\mycsvfil3.csv")
let pair = l.Split(',')
let id = Int32.Parse(pair[0].Trim())
orderby id
select new {
Id = id,
Name = pair[1].Trim()
};
From each string returned by ReadLines create an anonymous object with two properties (myIdentiaficiation and myName). Within the Select the context variable l represents a single line from the set returned by ReadLines.

Categories

Resources