12
votes

I tried to replace code

foreach (var discovery in mpwrapper.parser.Discoveries)
{
   solution.AddFile("Discoveries", discovery.DisplayStringName + ".mpx", discovery);
}

with the following linq expression

mpwrapper.parser.Discoveries.Select(
                    s => solution.AddFile("Discoveries", s.DisplayStringName + ".mpx", s));

But got an error

The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

How to convert this foreach loop to linq query where I execute a method on each object in my IEnumerable collection?

7
I'm guessing that your solution.AddFile method doesn't return anything - would that be correct?Dan Puzey
Select to execute code with side effects is improper use. Just do the foreach. Or List<T>.ForEach() which is a method that is expected to have side effects (= state changes outside the method).Gert Arnold
As an aside, changing foreach loops to Linq just for the sake of it is one of the most common techniques to make code harder to understand and debug that I'm aware of in .NET.Daniel Daranas

7 Answers

17
votes

I think what you need is the ForEach method ;)

mpwrapper.parser.Discoveries.ToList().ForEach(s => { solution.AddFile("Discoveries", s.DisplayStringName + ".mpx", s); });
6
votes

The problem is Select needs to return a value, but also Linq is not designed to mutate collections. Think of select as a transformation over the collection rather than a state change for each item

Maybe a foreach loop is the best solution here

4
votes

LINQ stands for Language INtegrated Query... yet you aren't actually querying anything.

If mpwrapper.parser.Discoveries is a List<T>, you can use the ForEach method; or, if it is an IEnumerable, you could always add a ForEach extension method… but this is more a minor aesthetic change and has nothing to do with LINQ.

2
votes

I use a little cheat with the .All method. It simply requires a return boolean value and presents very neatly. I included a sample with embeded linq inside the .All

configurations.All(c =>
{
    var gcx = globalConfigurations.FirstOrDefault(gc =>
        gc.Type == c.Type && configurationGuids.Any(cGuid => gc.Guid == cGuid)
    );
    return true;
});
1
votes

Try this:

mpwrapper.parser.Discoveries.ToList()
    .ForEach(s =>
        solution.AddFile("Discoveries", s.DisplayStringName + ".mpx", s));
1
votes

The List<T>.ForEach method does the trick.

However, this method does not exist on IEnumerable<T>.

0
votes

If Discoveries is a list, then do it like this

mpwrapper.parser.Discoveries.ForEach(discovery => solution.AddFile("Discoveries", discovery .DisplayStringName + ".mpx", discovery);

If not, convert it to List first :)