how to use a function as parameter in extension method? - c#

I have read that is recomended to use functions instead of predicates in the extension methods, so I am trying to do it.
public static void Insert<T>(this ObservableCollection<T> paramOC, T NewElement, Func<T, T, bool> condition)
{
//code
}
I am trying to use in this way:
myOC.Insert(myNewElement, e=>e.Name.CompareTo(myNewElement.Name) > 0));
But I get an error that says that the delete System.Func does not take 1 argument.
However, if I use a predicate intead of the function, it works.
What am I missing?
thank so much.

You need Func<T,bool> (which takes one argument and returns bool), not Func<T,T,bool>
Predicate<T> works because it takes one argument and returns bool, so it matches with the lambda expression.Func<T,T,bool> expects two arguments and returns bool which doesn't match with your expression hence the error.

Your Func<T,T,bool> takes 2 parameters and returns bool
You have two choise
as Selman22 says change it to Func<T,bool>
call it as (e1,e2) => ..

Related

Why when using String.contains in a Linq expression, are parentheses not required?

I was reading a solution on a coding exercise site and it was for determining if a sentence is a pangram and I came across this solution:
"abcdefghijklmnopqrstuvwxyz".All(input.ToLower().Contains);
For whatever reason, Contains() is not needed and this compiles just fine. I'm fairly inexperienced with the intricacies of LINQ, so I was wondering if anyone can answer or point me to an answer on this.
The reason Contains does not need the parentheses is because you are passing the function as the parameter to the All function and not the result of the function. If you look at the definition of All you see:
public static bool All<TSource> (this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,bool> predicate);
'All' is expecting a Func<TSource,bool>. In this case TSource is char so All is expecting the given parameter to be a reference to a function that receives a character and returns a boolean - which is exactly what Contains does.
You could also write it the following way and it will result in the same output (but might look a bit more messy): (For the difference see #pinkfloydx33's comment below)
"abcdefghijklmnopqrstuvwxyz".All(c => input.ToLower().Contains(c));
Firstly, you should look at the input type.
Here, All method takes input: Func<TSource, bool> predicate
All method is: public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
And Contains method is: public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value)
Now, we see that the Contains method is a delegate that is same as All method input predicate.
So, we pass the Contains method as a delegate, not the output of Contains method through the All method.
So, we should write:
"abcdefghijklmnopqrstuvwxyz".All(input.ToLower().Contains);
If we write : "abcdefghijklmnopqrstuvwxyz".All(input.ToLower().Contains());
then it return bool as All method input, that must not work.
But if we want to use parentheses then you may use it in this way:
"abcdefghijklmnopqrstuvwxyz".Contains(input)

Method with no parameters in c# and still a method?

All i am trying to do is to check whether all elements of list B are in list A
if (listA.All(element => listB.Contains(element))
{
return;
}
Someone came up with another solution saying this would work and it worked!
if (listA.All(listB.Contains))
return;
Now, (I know it works),
Why did the compiler doesn't require a () near contains in the second method?
If in future, say, I want this to compare case-insensitive, how would I do it with second method ?
Thanks in advance.
The All method asks for a predicate as a parameter: Func<T, bool> where T is the same type is the items in the List<T>. This code works because it provides just such a method. The All method will return a value indicating whether the result of calling the provided predicate on each item in the list results in true. The parameter is a reference to the Contains method which matches the required Func<T, bool>, taking a single parameter T and returning a bool.
Consider these two lines of code:
Func<string, bool> predicate1 = s => s.Length > 5;
Func<string, bool> predicate2 = listB.Contains;
Both of these lines work because the expressions to the right of the assignment operators evaluate to methods that take a single string parameter, and return a bool. You could pass predicate1 or predicate2 into the All method. It's the same as the code you provided, except that the predicate is passed directly, instead of being stored in a variable first and the variable passed in.
The Contains method is not actually called as the parameter though. It is only called internally by the All method.
If you wanted to do a case-insensitive search, and use the same sort of syntax as above, you would need a method that performed a case-insensitive search. You could always just use a custom anonymous method though:
listA.All(x => listB.Any(
z => string.Equals(x, z, StringComparison.OrdinalIgnoreCase)));

Why does .Where() on an IQueryable return a different type based on whether a Lamba or Func<T,Tresult> are passed as parameters

In my Entity Framework Code First project I have a repository object which contains routes
public class EFRepository
{
...
public IQueryable<Route> Routes
{
get { return context.Routes; }
}
...
}
If I run
var routes = this.repository.Routes
.Where(r => r.DeployedService.IsActive.HasValue
&& r.DeployedService.IsActive.Value);
The routes object is of type IQueryable<Route>.
However, if I run
Func<Route, bool> routeIsActive = r => r.DeployedService.IsActive.HasValue
&& r.DeployedService.IsActive.Value;
var routes = this.repository.Routes.Where(routeIsActive);
The routes object in this case is of type IEnumerable<Route>.
I would have thought that they would be evaluated the same but clearly I am wrong. What is the difference between the two statements and why do they return different types.
The method .Where(Expression<Func<Route,bool>>) is defined by IQueryable<Route>. The method .Where(Func<Route,bool>) on the other hand is defined by IEnumerable<Route> and not by IQueryable<Route>. Thus each returns its own type for fluent LINQ method chaining.
The additional method defined by IQueryable allows the expression tree to be pushed down to the LINQ provider, e.g. LINQ-to-entities, for lazy late evaluation at the provider level where this is possible.
Because passing Func<Route,bool> will make it Linq-to-objects (Func is .NET delegate which will be executed in .NET code). It tells EF: load all routes and I will do filtering in .NET code.
You need to pass an expression (Expression<Func<Route,bool>>) which will be internally translated to SQL to work with Linq-to-entities. It tells EF: here is the filter I want to translate to SQL and execute on the database server and I want to receive only filtered result set.
IQuerable<T> inherits from IEnumerable<T>. This means that Where is overloaded:
One overload takes an expression and returns an IQuerable<T>.
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
The other overload takes a function and returns an IEnumerable<T>.
public static IQueryable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
If you pass in a lambda, both overloads are applicable, and overload resolution prefers the first one. If you pass in a Func<T,bool>, then only the second overload is applicable.
If you change the type of your variable to Expression<Func<Route, bool>>, then you'll get an IQueryable<Route> back.

Can someone please explain the <Func<T, bool>> in a simple way for me

I am looking at code containing:
public virtual ICollection<T> GetPk(string pk)
{
Expression<Func<T, bool>> predicate = c => c.PartitionKey == pk;
return this.GetAll(predicate);
}
Can someone explain the syntax of <Func<T, bool>> ?
Simply Func<T, bool> is the anonymous method signature. The first type T is the input parameter type and the second type is the return type. This is more like a method when you consider your representation:
bool AnonMethod(T arg0)
{
return arg0.PartitionKey == pk;
}
One of the best explanation can be found at MSDN
You can use this delegate to represent a method that can be passed as a parameter without explicitly declaring a custom delegate. The encapsulated method must correspond to the method signature that is defined by this delegate. This means that the encapsulated method must have one parameter that is passed to it by value, and that it must return a value.
As for argument in your example T is the type of input parameter and bool is the return type of exacted method.
A Func<T, bool> represents a function that takes an object of type T and returns a bool. It's commonly referred to as a "predicate", and is used to verify a condition on an object.
An Expression<Func<T, bool>> represents the abstract syntax tree of the function, i.e. its syntactic structure. It can be used to analyse the code of the function for various purposes, such as transforming it to SQL to be executed against a database.
I always find MSDN to be worth checking on things like this first,
http://msdn.microsoft.com/en-us/library/bb549151.aspx
Beaten by Maheep, didn't see the post message pop-in.
Basically, you're declaring a method that matches a signature, that can then be passed in to the call to get the data.
It is confusing at first but Func<T, bool> describes a function that returns a bool and accepts a parameter as type T.
In this case, T is an object that has a PartitionKey property and this GetPk method is using the Func<T, bool> to match all the T items in the instance object which have a PartitionKey that matches the string pk.
For some background; prior to Func<T, TResult> (and the rest of this family) being part of the framework, you either had to explicitly define delegates or use anonymous methods.
Func and Action were added as part of the addition of lambda expressions to the language. They are the framework-defined delegates which lambda expressions are typed as, but which you as a developer can also use in place of your own custom delegate definitions.
You can get a nice history here;
http://blogs.msdn.com/b/ericwhite/archive/2006/10/03/lambda-expressions.aspx
It's additional syntax so you know what goes in and out of the function.
Func<T, bool> means:
function has 1 input T and 1 output that's bool.
This is other variations of the function

Generic Methods in C#

Generic Methods in general are new to me. Need a method that returns a Collection of a generic type, but also takes a collection of the same generic type and takes
Expression<Func<GenericType, DateTime?>>[] Dates
parameter. T throughout the following function should be the same type, so right now I was using (simplified version):
private static Collection<T> SortCollection<T>(Collection<T> SortList, Expression<Func<T, DateTime>>[] OrderByDateTime)
{
return SortList.OrderBy(OrderByDateTime[0]);
}
but i'm receiving error:
Error: The type arguments for method
'System.Linq.Enumerable.OrderBy(System.Collections.Generic.IEnumberable,
System.Func)' cannot be
inferred from the usage. Try
specifying the type arguments
explicitly.
Is there anyway to do this?
Sorry for answering twice, but this is legitimately another solution.
You're passing in an Expression<Func<T, DateTime>> but Orderby wants a Func<T, DateTime>
You can either compile the expression:
return new Collection<T>(SortList.OrderBy(OrderByDateTime[0].Compile()).ToList());
or pass in straight out funcs as arguments:
private static Collection<T> SortCollection<T>(Collection<T> SortList, Func<T, DateTime>[] OrderByDateTime)
{
return new Collection<T>(SortList.OrderBy(OrderByDateTime[0]).ToList());
}
I'd recommend reading up on Expressions on msdn
In this situation, the compiler is failing to figure out what type arguments you intend to provide to the OrderBy method, so you'll have to supply them explicitly:
SortList.OrderBy<T, DateTime>(OrderByDateTime[0])
You'll probably want to call ToList() if you want a Collection to be returned

Categories

Resources