Using LINQ or Lambda instead of nested and multiple foreach statements I want to use a better syntax than nested foreach statements to overwrite the initial list with items from the second list.

In the code below:


I want to overwrite initialList with those in secondList that have the same Value (Remove Red).
Use the items in secondList where Value was the same (Yellow)


New initialList list should include (Green and Yellow).

static void Main(string[] args)
{
    int useProd = 2;
    int useDomain = 0;

    var person1 = new Person() { prodId = 1, Value = "foo", domainId = 0, Name = "Red" };
    var person2 = new Person() { prodId = 1, Value = "bar", domainId = 0, Name = "Green" };
    var person3 = new Person() { prodId = 1, Value = "foo", domainId = 1, Name = "Yellow" };

    var initialList = new List&lt;Person&gt;();
    initialList.Add(person1);
    initialList.Add(person2);

    var secondList = new List&lt;Person&gt;();
    secondList.Add(person3);

    List&lt;Person&gt; personsToRemove = new List&lt;Person&gt;();
    List&lt;Person&gt; personsToUpdate = new List&lt;Person&gt;();

    foreach (var pers1 in initialList)
    {
        foreach (var pers2 in secondList)
        {
            if (pers1.Value == pers2.Value)
            {
                personsToRemove.Add(pers1);
                personsToUpdate.Add(pers2);
            }
        }
    }
    foreach (var remPers in personsToRemove)
    {
        initialList.Remove(remPers);
    }
    foreach (var updPers in personsToUpdate)
    {
        initialList.Add(updPers);
    }
    foreach (var item in initialList)
    {
        Console.WriteLine(String.Format("Value: {0}, prodId: {1}, domainId: {2}, Name: {3}", item.Value, item.prodId, item.domainId, item.Name));
    }

    Console.ReadKey();
}
public class Person
{
    public int prodId { get; set; }
    public string Value { get; set; }
    public int domainId { get; set; }
    public string Name { get; set; }
}
By using an IEqualityComparer&lt;Person&gt; which only compares the Value property like  

public class PersonValueComparer : IEqualityComparer&lt;Person&gt;
{
    public bool Equals(Person x, Person y)
    {
        if (x == null &amp;&amp; y == null) { return true; }
        if (x == null || y == null) { return false; }

        return x.Value == y.Value;
    }

    public int GetHashCode(Person obj)
    {
        if (obj == null || obj.Value == null) {return 0;}
        return obj.Value.GetHashCode();
    }
}  


you can by using linq methods replace the loops by  

        PersonValueComparer valueComparer = new PersonValueComparer();
        initialList = secondList.Where(p =&gt; initialList.Contains(p, valueComparer))
            .Concat(initialList.Where(p =&gt; !secondList.Contains(p, valueComparer))).ToList();


We are first using the Where() method to filter the secondList for items which are in the initialList . Then we use Concat() to add the Person''s which are not in thesecondList`.  



Based on the naming guidelines properties should be named using PascalCase casing.  



You should always use meaningful and descriptive names for naming methods, variables, properties and classes so Sam the Maintainer sees at first glance what it is about.  



Shortening variable names doesn't add any value but instead reduces readability which Sam the Maintainer doesn't like.