Is it possible to replace this foreach loop with Linq?

I have a foreach loop that I would like to replace with a Linq query, but I could not figure out how to write a query. See my example below and TIA.

using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication
{
    class ExampleProgram
    {
        static void Main( string[] args )
        {
            Device device = new Device();

            // The goal is to populate this list.
            var list1 = new List<IMemory>();

            // I would like to replace this loop with a Linq query
            foreach( MemoryBank memoryBank in device.MemoryBanks )
            {               
                list1.Add( memoryBank ); // add the memory bank

                foreach( MemoryBlock memoryBlock in memoryBank.MemoryBlocks )
                    list1.Add( memoryBlock ); // add the memory block
            }

            //var list2 = from memoryBank in device.MemoryBanks
            //            from memoryBlock in memoryBank.MemoryBlocks
            //            select ???;
        }
    }

    interface IMemory 
    {}

    public class Device
    { 
        public IList<MemoryBank> MemoryBanks { get; set; } 
    }

    public class MemoryBank : MemoryBlock, IMemory
    {
        public IList<MemoryBlock> MemoryBlocks { get; set; } 
    }

    public class MemoryBlock : IMemory 
    { }
}
+3
source share
2 answers

You can do:

var list1 = device.MemoryBanks
                  .SelectMany(m => new[] { m }.Concat(m.MemoryBlocks))
                  .ToList();

Note that this will create List<MemoryBlock>, not List<IMemory>, as in your example. To create a list of the interface type, make the final call ToList<IMemory>().

EDIT:

In .NET 3.5, in which the interface is IEnumerable<T>not covariant, you can do:

var list1 = device.MemoryBanks
                  .SelectMany(m => new IMemory[] { m }
                                       .Concat(m.MemoryBlocks.Cast<IMemory>()))
                  .ToList();
+5
source

Something like this should work:

list1 = device.MemoryBanks
              .Select( x=> x.MemoryBlocks.AsEnumerable<IMemory>().Concat(x))
              .SelectMany( x=>x)
              .ToList();
+1
source

All Articles