PjM PjM - 1 month ago 7
C# Question

C# - strange behaviour with ToList() and ToArray()

I noticed some strange behavior when using a combination of ToList() and ToArray() in C# (using the .NET 4.5.2 famework).

Given the following test program:

int[] array = { 5, 1, -10, 667, 4 };
SorteerBib<int>.SelectionSort(array, Comparer<int>.Default);
Console.Out.WriteLine("Result - WRONG!");
for (int i = 0; i < array.Length; i++)
{
Console.Out.Write(array[i] + " ");
Console.Out.WriteLine();
}
Console.ReadKey();


The SorteerBib class consists of 2 methods:

class SorteerBib<T>
{
public static IList<T> SelectionSort(IList<T> list, IComparer<T> comparer)
{
for (int i = 0; i < list.Count - 1; i++)
{
int minIndex = i;
for (int j = i + 1; j < list.Count; j++)
{
if (comparer.Compare(list[j], list[minIndex]) < 0)
{
minIndex = j;
}
}
T temp = list[i];
list[i] = list[minIndex];
list[minIndex] = temp;
}

Console.Out.WriteLine("Result SelectionSort IList - OK");
for (int i = 0; i < list.Count; i++)
{
Console.Out.Write(list[i]+" ");
Console.Out.WriteLine();
}
return list;
}

public static void SelectionSort(T[] array, IComparer<T> comparer)
{
// DOES NOT WORK, WHY?
array = ((SelectionSort(array.ToList(), comparer)).ToArray());

Console.Out.WriteLine("Result SelectionSort Array - OK");
for (int i = 0; i < array.Length; i++)
{
Console.Out.Write(array[i] + " ");
Console.Out.WriteLine();
}
}
}


The error lies within the first line of the second method:

array = ((SelectionSort(array.ToList(), comparer)).ToArray());


Within the void method, the array is sorted after this line, but once we return to the main program the sorting is gone.

Replacing this line with the following lines however fixes this issue:

IList<T> temp = SelectionSort(array.ToList<T>(), comparer);
for (int i = 0; i < array.Length; i++) {
array[i] = temp[i];
}


Can anyone explain this unpredictable behavior?
Many thanks in advance!

Answer

You are passing the array without the ref keyword and then changing it's reference by doing:

array = ((SelectionSort(array.ToList(), comparer)).ToArray());

Since the ref keyword is not used, the change applies only in the function.

The fix will be to add the ref keyword:

public static void SelectionSort(ref T[] array, IComparer<T> comparer)

BTW a better approach will be to sort an ICollection<T> or an IEnumerable<T> instead.