2016-10-21 4 views
2

Я заметил странное поведение при использовании комбинации ToList() и ToArray() в C# (с использованием команды .NET 4.5.2).C# - странное поведение с ToList() и ToArray()

Учитывая, следующая программа тестирования:

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(); 

Класс SorteerBib состоит из 2-х способов:

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(); 
     } 
    } 
} 

Ошибка лежит в первой строке второго метода:

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

Внутри метода void массив сортируется после этой строки, но как только мы вернемся к основной проге ram сортировка исчезла.

Замена этой линии следующие строки, однако устраняет эту проблему:

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

Может кто-нибудь объяснить это непредсказуемое поведение? Большое спасибо заранее!

+3

Нет непредсказуемого поведения, передайте массив как byref, тогда он будет работать, второй подход работает, потому что вы заменяете элементы в массиве, а не самим массивом. – Gusman

+0

Возможный дубликат [ToList() - создает ли он новый список?] (Http://stackoverflow.com/questions/2774099/tolist-does-it-create-a-new-list) – Juan

+1

FYI массивы реализуют ' IList ', поэтому нет необходимости во втором методе или вызове' ToList' при передаче массива в первый. – juharr

ответ

0

Вы передаете массив без ref ключевого слова, а затем изменить это ссылка, выполнив:

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

Поскольку ref ключевого слова не используется, то изменение применяется только в функции.

Исправление будет добавить ref ключевое слово:

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

BTW лучший подход будет сортировать ICollection<T> или IEnumerable<T> вместо этого.

+0

Сортировка 'IEnumerable ' будет лучше возвращать его вместо изменения переданного в ссылке. – juharr

+0

@juharr - Я знаю, но я думаю, что лучше преобразовать массивы в списки и наоборот. –

+0

На самом деле нет необходимости преобразовывать массив в первую очередь, поскольку он реализует 'IList '. – juharr