2009-10-22 10 views
22

Dans LINQ, il est possible d'avoir un ordre conditionnel par ordre de tri (croissant ou décroissant).Ordre de tri "orderby" conditionnel dans LINQ

Quelque chose comme ça (pas de code valide):

bool flag; 

(from w in widgets 
where w.Name.Contains("xyz") 
orderby w.Id (flag ? ascending : descending) 
select w) 

Répondre

25

Si vous construisez l'expression, vous pouvez le faire progressivement. En général, plus facile en utilisant des expressions plutôt que des expressions de compréhension:

var x = widgets.Where(w => w.Name.Contains("xyz")); 
if (flag) { 
    x = x.OrderBy(w => w.property); 
} else { 
    x = x.OrderByDescending(w => w.property); 
} 

(. En supposant property de la widget base de tri puisque vous ne listez pas)

+0

comment faire plusieurs commande avec des conditions dynamiques si elles sont nécessaires ou non. – Ruchan

+0

Juste besoin d'utiliser une variable différente pour le résultat de 'OrderBy' et' ThenBy' pour garder le type de retour différent; sinon, ajoutez simplement des appels à l'opérateur LINK 'ThenBy' ou' ThenByDescending' applicable. – Richard

8

Vous pouvez définir une requête de base sans la commande, puis commande selon le drapeau:

var query=(from w in widgets 
    where w.Name.Contains("xyz") 
    select w); 

var result = flag ? 
    query.OrderBy(w =>w) : 
    query.OrderByDescending(w = w); 
8

Vous pouvez essayer quelque chose comme ce qui suit:

var q = from i in list 
     where i.Name = "name" 
     select i; 
if(foo) 
    q = q.OrderBy(o=>o.Name); 
else 
    q = q.OrderByDescending(o=>o.Name); 
14

... Ou le faire en une seule déclaration

bool flag; 

var result = from w in widgets where w.Name.Contains("xyz") 
    orderby 
    flag ? w.Id : 0, 
    flag ? 0 : w.Id descending 
    select w; 
+0

Si les données sous-jacentes sont en SQL, cette réponse semble la plus susceptible d'utiliser la clause ORDERBY de SQL, mais je ne le sais pas pour un fait. –

1

Si la propriété de commande Id est un numéro (ou prend en charge le moins unaire) on pourrait aussi faire:

bool ascending = ... 

collection.Where(x => ...) 
    .OrderBy(x => ascending ? x.Id : -x.Id) 
    .Select(x => ...) 

// LINQ query 
from x in ... 
orderby (ascending ? x.Id : -x.Id) 
select ... 
0

Le MoreLINQ NuGet package fournit également des méthodes d'extension pour rendre this plus pratique. Il fournit également beaucoup plus de méthodes d'extension utiles et est donc une référence stable dans mes projets.

3

Voici une solution plus générale, qui peut être utilisée pour diverses expressions lambda conditionnelles sans casser le flux de l'expression.

public static IEnumerable<T> IfThenElse<T>(
    this IEnumerable<T> elements, 
    Func<bool> condition, 
    Func<IEnumerable<T>, IEnumerable<T>> thenPath, 
    Func<IEnumerable<T>, IEnumerable<T>> elsePath) 
{ 
    return condition() 
     ? thenPath(elements) 
     : elsePath(elements); 
} 

par exemple.

var result = widgets 
    .Where(w => w.Name.Contains("xyz")) 
    .IfThenElse(
     () => flag, 
     e => e.OrderBy(w => w.Id), 
     e => e.OrderByDescending(w => w.Id)); 
0

Vous pouvez même faire la commande plus complexe et toujours garder court:

var dict = new Dictionary<int, string>() { [1] = "z", [3] = "b", [2] = "c" }; 
    var condition = true; 
    var result = (condition ? dict.OrderBy(x => x.Key) : dict.OrderByDescending(x => x.Value)) 
     .Select(x => x.Value);