Comment trier une liste d'objets par un champ spécifique en C#?
J'ai cette classe:
public class StatInfo
{
public string contact;
public DateTime date;
public string action;
}
puis-je avoir une liste de StatInfo, mais je ne suis pas sûr de la façon de les trier selon la date de champ. Dois-je utiliser la méthode de tri? Dois-je créer mon propre?
var _allStatInfo = new List<StatInfo>();
//adding lots of stuff in it
_allStatInfo.SortByDate???
Quelle est la meilleure façon de le faire sans avoir à écrire des tonnes de code (si possible)?
Grâce
- Attendre Jon Skeet de montrer. Son C# en Profondeur: Ce que vous devez à la maîtrise de C# 2 et 3 a une grosse section sur tout ce qui.
- Trop tard! Je suis toujours surpris quand un de mes questions sur le C# ne pas obtenir une réponse de Jon Skeet 🙂
- le titre est faux. dit "array"
Vous devez vous connecter pour publier un commentaire.
À l'aide de LINQ:
De tri de la liste d'origine:
Je vois que vous avez la réponse, de toute façon, mais...
Vous pouvez éviter certains laideur par juste le fractionnement de la déclaration en deux moitiés:
Vous pourriez envisager d'appeler
CompareTo
directement, trop:Vous pouvez créer une
IComparer<T>
mise en œuvre à l'aide de monProjectionComparer
classec'est une partie de MiscUtil, et j'ai inclus une version sans commentaire au bas de
cette réponse. Vous devez ensuite écrire:
Même si vous êtes en utilisant .NET 2.0, vous pouvez toujours utiliser LINQ par LINQBridge.
Voici la
ProjectionComparer
classe requise pour la deuxième réponse. Les deux premières classes sont vraiment juste des aides pour laisser l'inférence de type générique fonctionne mieux.Compare
méthode, sont nulles vérifie vraiment nécessaire? Qui devrait être laissé à l'appelant.foo => foo.Name
sans avoir à fairefoo => foo == null ? null : foo.Name
de l'OMI.Compute(int, string)
comme la projection, comme_allStatInfo.Sort(ProjectionComparer<StatInfo>.Create(x => Compute(someInt, x)))
où la valeur null pourx
est parfaitement acceptable? Lancer une référence nulle exception ou d'ignorer une valeur null devrait être à la discrétion de la projection si cela doit être entièrement générique..Comparer<T>.Default
prend.Comparer<T>.Default
parce queDefault
comparex
ety
(votre exemple) en tant que tel, et non pas une projection dex
ety
. Dans un tel cas, il est parfaitement logique pour gérer les valeurs null, parce que l'ensemble de la logique de comparaison est dans leIComparer<T>
mise en œuvre.Compare
méthode. Je comprends le désagrément de l'appelant s'il s'agit de vérifier les valeurs null à l'avance, et il est convenu que c'est la majorité des cas. Mais mon point est qu'il y a pas de contrat original ici en cas de projections. À moins que le contrat ne couvre pas tous les scénarios.x == null
&y != null
, & si nous avons à comparerx
&y
, le contrat initial seraitx < y
comme vous le dites, ce qui est correct. Mais si nous avons à comparerprojection(x)
&projection(y)
oùx
&y
peut être nulle, alors il n'y a pas de contrat d'origine - tout dépend du contexte de l'appelant. C'est là que votre tentative échoue. Ce que j'essaie de dire, c'est il y a un bug dans votre code, mais il est rare. Par exemple,new[] { "-1", null, "1" }.Sort(ProjectionComparer<string>.Create(x => Convert.ToInt32(x)))
votre code renvoie[null, "-1", "1"]
mais attendu est["-1", null, "1"]
IComparer<T>.Compare
, tandis que d'autres projections ne pourrait pas. Après tout, nous est être demandé de comparerx
ety
, et la comparaison est par l'intermédiaire d'une projection - votre "attendre" les résultats de violer le marché documenté, même si c'est ce que vous voulez vraiment._allStatInfo.Sort(ProjectionComparer<StatInfo>.Create(x => x.date))
il devrait régler_allStatInfo
basé sur ladate
propriété des objets indépendamment de l'élément. Sinon, sur quelle base est quelque chose commeitems.OrderBy(x => Guid.NewGuid())
écrit? Mais vous dire qu'il devrait être respectif de l'élément. Pouvez-vous m'indiquer une documentation à ce sujet? Je suis désolé d'avoir dérangé avec cette. Je vais faire une nouvelle question si elle justifie..IComparer<T>.Compare
est ici: msdn.microsoft.com/en-us/library/xh5ks3b3.aspx Vous pourriez certainement faire valoir queIComparer<T>
a été mal conçu sur ce front, maisProjectionComparer<T>
est destinée à mettre en place, et je crois que votre suggestion serait fondamentalement violer le contrat.IComparer<T>
sur null-throwable implémentations, commefoo.Name
(qui est la norme généralement) qui a du sens. Mais dans un générique de mise en œuvre, comme la vôtre, je voudrais l'éviter. Ou encore mieux, peut-être que nous pourrions prendre unExpression<Func<>>
comme entrée et de mettre en œuvre un fou approche hybride! 🙂Compare
méthode. Encore une fois, qui peut avoir été une mauvaise idée - mais il est le comportement documenté.Compare
méthode jeter référence nulle exception. De plus, comme il a été considéré que pour lesfoo.Name
scénarios. 2. J'ai senti qu'il était logiquement incorrecte à ignorer les valeurs nulles sans savoir ce que la projection ne faire avec cette valeur null. Jon, sur une seconde pensée, je pense que MS l'idée a du sens aussi. Surtout quand vous avez dit: Après tout, on nous demande de comparer x et y, et la comparaison est par l'intermédiaire d'une projectionPour illustrer Robert C. Cartaino réponse:
Pas la plus générale de la solution, mais bon si vous allez seulement pour trier par date. Et, comme Robert a dit, vous pouvez toujours remplacer la valeur par défaut tri par le passage d'un IComparer paramètre à la méthode de tri.
Utiliser une expression lambda à la carte d'une paire à une comparaison:
il a travaillé pour moi ُDe tri de tableau de type personnalisé à l'aide de délégué
Pour un DateTime il ne devrait pas être nécessaire de comparer.
ou