0

How can I check for NULL value in lambda expression having ForEach and Find methods.

For instance I've a below method which takes a comma separated list of values, iterate through them and for each value finds a SelectListItem which if found is marked as Selected. The issue comes when no matching item is found and it throws null reference exception.

private static void MarkListItemsSelected(string param, IList<SelectListItem> items)
{
    var filters = param.Split(';');
    filters.ToList()
     .ForEach(x => items.ToList()
                   .Find(y => y.Text.ToUpper().Equals(x.ToUpper()))
                   .Selected = true);
}
12
  • 1
    You don't need ToList(), it will split into an Array. Commented Aug 27, 2015 at 20:38
  • @Greg Arrays do not have a ForEach method. Commented Aug 27, 2015 at 20:42
  • @juharr They don't, but it is the equivalent of foreach so why create a List for ForEach when you could just do foreach. Commented Aug 27, 2015 at 20:43
  • items.ToList() is definitely unwarranted. Commented Aug 27, 2015 at 20:43
  • @Greg I totally agree and think ForEach is an abomination, but your comment sounded like they could just remove the ToList. Commented Aug 27, 2015 at 20:44

2 Answers 2

5

Linq example:

private static void MarkListItemsSelected(string param, IList<SelectListItem> items)
{
    var filters = param.ToUpper().Split(';');

    items.ToList()
         .ForEach(x => { x.Selected = filters.Contains(x.Text.ToUpper());});
}

Traditional loops:

private static void MarkListItemsSelected(string param, IList<SelectListItem> items)
{
    var filters = param.ToUpper().Split(';');

    foreach( var x in items ) {
        x.Selected = filters.Contains(x.Text.ToUpper());
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

I think the ToList() and Where parts are flipped here. EDIT: That is, should be items.Where(...).ToList().ForEach(...);
Better yet, just use a foreach instead and there is no need for the ToList.
Ugh, side effects in Linq, please no.
I think the edited use of .All here is a step backward. Either use a ToList().ForEach or a foreach loop, but not .All; that would be abusing the query nature of LINQ introducing side effects. Plus it's weird, rarely seen code. Plus it hinges on the fact that the property being changed (.Selected) happens to be a boolean.
One minor quibble with the latest edit (sorry!), the "traditional loops" version has slightly different behaviour in that the original code would not change the current value of the SelectedListItem if it didn't match the filter. That is, if it were true originally, and it didn't match, it stayed true. This new code would set it to false. (That said, this may actually be a good thing for the OP, but I think it should be noted regardless.) EDIT: Actually, it's even worse: it could match an early filter, then be made false by a filter that doesn't match. I would consider it bugged.
|
1

Just add a null check to lambda:

private static void MarkListItemsSelected(string param, IList<SelectListItem> items)
{
    var filters = param.Split(';');
    filters.ToList().ForEach(
        x =>
        {
            var found = items.ToList().Find(y => y.Text.ToUpper().Equals(x.ToUpper()));
            if (found != null)
                found.Selected = true;
        });
}

4 Comments

If you're going to have a multi-line lambda in a ForEach you might as well just use foreach.
@juharr I agree but was simply answering the question asked :)
IMHO there is nothing in that question that would required you to give an answer that uses ForEach
Actually the title says "foreach" not "ForEach". So based on your logic we should only give foreach answers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.