-3

I am writing a method that gets a lambda expression as a parameter to be used to filter the IList<SomeModel> _collection.

public void DoSomething(SomeModel model)
{
   FilterCollectionUsingPredicate(x => x.Name.Equals(model.Name));
}

private void FilterCollectionUsingPredicate(Func<SomeModel, bool> predicate)
{
   _collection = _collection.Where(predicate).ToList();
}

It works well when the predicate parameter is a simple expression, like x => x.Name.Equals(model.Name). However, it gets tricky when it has to use some other (local) collection and Contains clause.

public void DoSomething(SomeModel model)
{
   IEnumerable<string> someOtherCollection = model.SomeOtherCollection;
   FilterCollectionUsingPredicate(x => someOtherCollection.Contains(x.Phone));
}

private void FilterCollectionUsingPredicate(Func<SomeModel, bool> predicate)
{
   _collection = _collection.Where(predicate).ToList();
}

Of course, FilterCollectionUsingPredicate method does not see someOtherCollection and therefore, throws an error. Can someone explain how to properly define and use this function to handle such a case?

MajQ
  • 1
  • 1
  • 1
    What error is thrown? FYI `someOtherCollection` will be captured as part of the lambda that is pasted. – juharr Apr 16 '20 at 18:11
  • i think ``predicate`` must be ``Expression`` not a ``Fun``. – Mohammed Sajid Apr 16 '20 at 18:14
  • 1
    You're going to have to add more detail, as I've attempted to reproduce this and it's working just fine. At the very least we need to know the error. – juharr Apr 16 '20 at 18:14
  • @Sajid I doubt it because of the use of `ToList` when assigning to `_collection` would indicate we are not dealing with an `IQueryable`. But `_collection` might be an `IEnumerable` that the OP assigns an `IQueryable` to first. Just another reason for the OP to give more details. – juharr Apr 16 '20 at 18:15
  • @juharr: you are right, the solution in the question, it's work fine. no error. – Mohammed Sajid Apr 16 '20 at 18:24

1 Answers1

0

Well try and create a generic extension instead, Expression should keep track of all other data in the expression. Try and create the predicate as Expression

private void FilterCollectionUsingPredicate(Expression<Func<SomeModel, bool>> predicate)
{
   _collection = _collection.Where(predicate).ToList();
}

It should work.

Alen.Toma
  • 4,684
  • 2
  • 14
  • 31
  • 2
    This might be the answer, but nothing in the question implies that it is. – juharr Apr 16 '20 at 18:18
  • Func dose not keep track of all other external items, and that why your geting error. Expression keep track or path to the orginal items in the expression – Alen.Toma Apr 16 '20 at 18:19
  • 1
    @Alen.Toma That is entirely incorrect. All local variables in a lambda of type `Func<>` are captured. – NetMage Apr 16 '20 at 18:21
  • 1
    You'd only need it to be an Expression if the provider is going to translate the code like EF does to translate to SQL. If this is using Linq-to-Objects then the lambda will capture any variables used inside of it's closure. – juharr Apr 16 '20 at 18:50