Diff comparison for List List&lt;string&gt; difference tool for two input List&lt;string&gt; listA and listB

Output List&lt;string&gt;


both - in both listA and listB
listAonly - in listA only 
listBonly - in listB only 


Looking for speed, space, and style  

. 

//test
List&lt;string&gt; both;
List&lt;string&gt; both;
List&lt;string&gt; listAonly;
List&lt;string&gt; listBonly;
ListDiff( new List&lt;string&gt;() { "AAA", "BBB", "CCC", "DDD", "GGG", "FFF", "BBB", "GGG" }
        , new List&lt;string&gt;() { "AAA", "BBB", "DDD", "FFF", "EEE", "FFF", "EEE" }
        , false, out both, out listAonly, out listBonly );
Debug.WriteLine("both");
foreach (string s in both)
    Debug.WriteLine($"  {s}");
Debug.WriteLine("listAonly");
foreach (string s in listAonly)
    Debug.WriteLine($"  {s}");
Debug.WriteLine("listBonly");
foreach (string s in listBonly)
    Debug.WriteLine($"  {s}");
//end test

public static void ListDiff(List&lt;string&gt; listA, List&lt;string&gt; listB, bool ignoreCase, out List&lt;string&gt; both, out List&lt;string&gt; listAonly, out List&lt;string&gt; listBonly)
{
    both = new List&lt;string&gt;();
    listAonly = new List&lt;string&gt;();
    listBonly = new List&lt;string&gt;();

    IEnumerable&lt;string&gt; listAsorted = listA.OrderBy(x =&gt; x).Distinct();
    IEnumerable&lt;string&gt; listBsorted = listB.OrderBy(x =&gt; x).Distinct();

    var listAenumerator = listAsorted.GetEnumerator();
    var listBenumerator = listBsorted.GetEnumerator();

    bool listAcanmove = listAenumerator.MoveNext();
    bool listBcanmove = listBenumerator.MoveNext();

    while (listAcanmove | listBcanmove)
    {
        string valueA = listAenumerator.Current;
        string valueB = listBenumerator.Current;

        //Debug.WriteLine($"valueA = {valueA}");
        //Debug.WriteLine($"valueB = {valueB}");

        if (!listAcanmove &amp;&amp; listBcanmove)
        {
            //Debug.WriteLine($"{valueB} in B not in A");
            listBonly.Add(valueB);
            listBcanmove = listBenumerator.MoveNext();
        }
        if (listAcanmove &amp;&amp; !listBcanmove)
        {
            //Debug.WriteLine($"{valueA} in A not in B");
            listAonly.Add(valueA);
            listAcanmove = listAenumerator.MoveNext();
        }
        else
        {
            int comp = string.Compare(valueA, valueB, ignoreCase);
            if (comp == -1)
            {
                //Debug.WriteLine($"{valueA} in A not in B");
                listAonly.Add(valueA);
                listAcanmove = listAenumerator.MoveNext();
            }
            else if (comp == 1)
            {
                //Debug.WriteLine($"{valueB} in B not in A");
                listBonly.Add(valueB);
                listBcanmove = listBenumerator.MoveNext();
            }
            else
            {
                //Debug.WriteLine($"{valueA} {valueB} in B and A");
                both.Add(valueA);
                listAcanmove = listAenumerator.MoveNext();

                listBcanmove = listBenumerator.MoveNext();
            }
        }
        //Debug.WriteLine("");
    }
    //Debug.WriteLine($"done");
}
I wouldn't want to maintain this code. Unless you have proven that this code is a performance problem, do the simple thing. Yes, the following solution will iterate over the lists 3 times. No, I don't care that it does. 

var both = listA.Intersect(listB);
var listAOnly = listA.Except(listB);
var listBOnly = listB.Except(listA);


If you're worried about case insensitivity, pass in a StringComparer.