I was wondering if I could replace this foreach with LINQ queries somehow (if possible):
Online playpen: https://ideone.com/PQEytf
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public static void Main()
{
// dummy inputs for test sake
var keys = new[] { "key1", "key2" };
var services = new Dictionary<string, Service>
{
{"key1", new Service {Components = new Dictionary<string, string> {{"comp1", "value1"}}}},
{"key2", new Service {Components = new Dictionary<string, string> {{"comp2", "value2"}}}}
};
var serviceComponents = GetServiceComponents(keys, services);
// do something with it
}
public static IEnumerable<ServiceComponent> GetServiceComponents(string[] keys, Dictionary<string, Service> services)
{
var serviceComponents = new List<ServiceComponent>();
// this is the foreach that I want to lose
foreach (
var key in
keys.Select(
name =>
services.FirstOrDefault(
x => x.Key.Equals(name))))
{
serviceComponents.AddRange(key.Value.Components.Select(component => new ServiceComponent
{
Name = key.Key,
Service = component.Key,
Value = component.Value,
}));
}
return serviceComponents.ToArray();
}
}
public class Service
{
public Dictionary<string, string> Components { get; set; }
}
public class ServiceComponent
{
public string Name { get; set; }
public string Service { get; set; }
public string Value { get; set; }
}
What you need is
SelectMany, however, by usingFirstOrDefaultyou're opening yourself up to aNullReferenceException(as the default value for any reference type isnull). If you intend to have aNullReferenceExceptionthrown when an element ofkeysis not a key inservicesthen you can use other answers which leverageSelectMany. However, is you do not intend aNullReferenceException, then you should use something like the following:This statement removes all key-value pairs from
serviceswhose key is not in thekeysarray, then turns each element of each pair'sComponentsinto a newServiceComponentobject, with theSelectManymaking a single flat list out of the newServiceComponents.