2016-10-21 4 views
2

J'ai remarqué un comportement étrange lors de l'utilisation d'une combinaison de ToList() et ToArray() en C# (en utilisant le famework .NET 4.5.2).C# - comportement étrange avec ToList() et ToArray()

Compte tenu du programme de test suivant:

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

La classe SorteerBib se compose de 2 méthodes:

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

L'erreur se situe dans la première ligne du deuxième méthode:

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

Dans la méthode void, le tableau est trié après cette ligne, mais une fois que nous revenons au prog principal ram le tri est parti.

Le remplacement de cette ligne avec les lignes fixe cependant cette question ci-dessous:

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

Quelqu'un peut-il expliquer ce comportement imprévisible? Merci beaucoup d'avance!

+3

Il n'y a pas de comportement imprévisible, passez le tableau comme byref, alors ça va marcher, la deuxième approche fonctionne parce que vous remplacez des éléments dans le tableau, pas le tableau lui-même. – Gusman

+0

Copie possible de [ToList() - Crée-t-il une nouvelle liste?] (Http://stackoverflow.com/questions/2774099/tolist-does-it-create-a-new-list) – Juan

+1

Les tableaux FYI implémentent ' IList ', donc pas besoin de la seconde méthode ou d'appeler' ToList' lors du passage d'un tableau à la première. – juharr

Répondre

0

Vous passez le tableau sans le mot-clé ref puis changer en faisant référence est:

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

Depuis le mot-clé ref n'est pas utilisé, le changement ne s'applique que dans la fonction.

Le correctif sera d'ajouter le mot-clé ref:

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

BTW une meilleure approche sera de trier un ICollection<T> ou un IEnumerable<T> à la place.

+0

Le tri d'un 'IEnumerable ' serait préférable de le retourner au lieu de changer le passé dans la référence. – juharr

+0

@juharr - Je sais, mais je pense que c'est mieux que de convertir des tableaux en listes et vice versa. –

+0

Il n'y a en fait pas besoin de convertir le tableau en premier lieu puisqu'il implémente 'IList '. – juharr