0

I am wondering on how to do the following. I have the Linq query:

Items items.Where(i => i.GetType() == typeof(SubItem))
                .Cast<SubItem>()
                .ToList()
                .ForEach(i => i.SomeList.Add(i.SomeObject.ForEach(i => i.SomeString)));

My question is about i.SomeList.Add(). I want to return a couple of string values to i.SomeList.Add() from i.SomeObject but I do not know how I can do this in this way? Is it even possible like this to have another ForEach Loop within a Linq ForEach usinq Linq query?

7
  • 5
    ForEach is a List method, not LINQ. LINQ is a query language. Why use it at all if you want nested loops? Commented Jan 22, 2021 at 20:15
  • 1
    ForEach is absolutely wrong here as are Cast, i.GetType() == typeof(SubItem), and ToList Commented Jan 22, 2021 at 20:16
  • 3
    .Where(i => i.GetType() == typeof(SubItem)).Cast<SubItem>() is equivalent to OfType<SubIttem>(). What are you trying to do anyway? ForEach doesn't return anything, so i.SomeArray.Add(i.SomeObject.ForEach won't even compile. Whatever you want to do, it's far easier to do with simple loops Commented Jan 22, 2021 at 20:18
  • 1
    Maybe you want i.SomeArray.AddRange(i.SomeObject.Select(x => x.SomeString)) though that only works if SomeArray is a List<T> and not an array as the name implies. Commented Jan 22, 2021 at 20:26
  • 1
    GetType() is slow and will miss any types that derive from SubItem. ToList isn't necessarily wrong but it's confusing here and people often use it without thinking. Instead use foreach (var item in items.OfType<SubItem>()) {...} Commented Jan 22, 2021 at 21:08

2 Answers 2

3

I believe this foreach loop will achieve your goal, if I've understood the problem.

It will loop over any element of items that is a (or is derived from) SubItem. It will then select all SomeObject.SomeString strings and add them to the SomeList.

foreach (var subItem in items.OfType<SubItem>()) {
    subItem.SomeList.AddRange(subItem.SomeObject.Select(o => o.SomeString));
}

This is a compilation of suggestions from Panagiotis Kanavos, juharr, and Aluan Haddad.

Sign up to request clarification or add additional context in comments.

Comments

1

LINQ isn't really for running Add operations... it's much more powerful when you think of it as returning a resultset.

So instead of

//Add every value of SomeField to targetList
sourceList.ForEach( x => targetList.Add(x.SomeField) )

Think of doing it this way:

//Create a list of all instances of SomeField and assign it to targetList
targetList = sourceList.Select( x => x.SomeField).ToList();

Or if you need to keep the existing items in the target list, do this:

//Create a list of all SomeFields and add it to targetList
targetList.AddRange
(
     sourceList.Select( x => x.SomeField )
);

Similarly, instead of using a nested foreach, consider using SelectMany.

I'm not completely clear on your requirements but you probably want something like this:

//To SomeList, add the SomeString field from all instances of SomeObject
someList.AddRange
(
    items.OfType<SubItem>().SelectMany( x => x.SomeObject ).Select( x => x.SomeString )
);

Comments

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.