J'utilise les instructions LINQ to Objects sur un tableau ordonné. Quelles opérations dois-je ne pas faire pour m'assurer que l'ordre du tableau n'est pas modifié?
J'ai examiné les méthodes de System.Linq.Enumerable , en ignorant celles qui renvoyaient des résultats non IEnumerable. J'ai vérifié les remarques de chacun pour déterminer comment l'ordre du résultat serait différent de l'ordre de la source.
Conserve l'ordre absolument. Vous pouvez mapper un élément source par index sur un élément de résultat
Préserve l'ordre. Les éléments sont filtrés mais non réorganisés.
Détruit l’ordre - nous ne savons pas dans quel ordre attendre des résultats.
Redéfinit explicitement l'ordre - utilisez-les pour modifier l'ordre du résultat
Redéfinit l'ordre selon certaines règles.
Edit: J'ai déplacé Distinct to Conserver l'ordre en fonction de ceci implémentation .
private static IEnumerable<TSource> DistinctIterator<TSource>
(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
Parlez-vous réellement de SQL, ou de tableaux? En d'autres termes, utilisez-vous LINQ to SQL ou LINQ to Objects?
Les opérateurs LINQ to Objects ne changent pas réellement leur source de données d'origine - ils construisent des séquences qui sont effectivement sauvegardées par la source de données. Les seules opérations qui modifient l'ordre sont OrderBy/OrderByDescending/ThenBy/ThenByDescending - et même dans ce cas, elles sont stables pour des éléments de même ordre. Bien sûr, de nombreuses opérations filtreront certains éléments, mais les éléments renvoyés seront dans le même ordre.
Si vous convertissez une structure de données différente, par exemple, avec ToLookup ou ToDictionary, je ne crois pas que l'ordre soit préservé à ce stade - mais c'est un peu différent de toute façon. (Je crois que l'ordre des valeurs mappant sur la même clé est conservé pour les recherches.)
Si vous travaillez sur un tableau, il semblerait que vous utilisiez LINQ-to-Objects, pas SQL; pouvez-vous confirmer? La plupart des opérations LINQ ne réordonnent rien (la sortie sera dans le même ordre que l'entrée) - aussi, n'appliquez pas un autre tri (OrderBy [Décroissant]/ThenBy [Décroissant]).
[edit: comme Jon l'a dit plus clairement; LINQ crée généralement une séquence nouvelle, laissant les données d'origine seules]
Notez que l'insertion des données dans un Dictionary<,>
(ToDictionary) brouillera les données, car le dictionnaire ne respecte aucun ordre de tri particulier.
Mais les choses les plus courantes (Select, Where, Skip, Take) devraient bien se passer.
J'ai trouvé une excellente réponse à une question similaire qui fait référence à la documentation officielle. Pour le citer:
Pour les méthodes Enumerable
(LINQ to Objects, qui s'applique à List<T>
), Vous pouvez vous fier à l'ordre des éléments renvoyés par Select
, Where
ou GroupBy
. Ce n'est pas le cas pour des choses non ordonnées par nature, comme ToDictionary
ou Distinct
.
De Enumerable.GroupBy documentation:
Les objets
IGrouping<TKey, TElement>
Sont générés dans un ordre basé sur l'ordre des éléments de la source qui ont généré la première clé de chaqueIGrouping<TKey, TElement>
. Les éléments d'un groupe sont générés dans l'ordre dans lequel ils apparaissent danssource
.
Ce n'est pas nécessairement vrai pour les méthodes d'extension IQueryable
(autres fournisseurs LINQ).
Source: Les méthodes énumérables de LINQ maintiennent-elles l'ordre relatif des éléments?
Tout 'groupe par' ou 'ordre par' changera éventuellement l'ordre.
La question ici fait spécifiquement référence à LINQ-to-Objects.
Si vous utilisez LINQ-to-SQL à la place, il n'y a pas d'ordre à moins d'en imposer un avec quelque chose comme:
mysqlresult.OrderBy(e=>e.SomeColumn)
Si vous ne le faites pas avec LINQ-to-SQL, l'ordre des résultats peut varier entre les requêtes suivantes, même pour les mêmes données, ce qui peut provoquer un bogue intermittent.