Pour quel domaine problématique LINQ est-il conçu?

12

Chaque fois que je vois une question publiée sur Stack Overflow sur C #, je vois au moins une ou deux réponses publiées qui résolvent un problème avec LINQ. Habituellement, les personnes ayant une très bonne réputation semblent utiliser LINQ comme des pros.

Donc ma question est, pour quel domaine problématique LINQ est-il censé être utilisé?

Également sur les notes annexes: Y a-t-il des raisons pour lesquelles cela devrait être évité? La taille de l'ensemble de données affecte-t-elle les performances des requêtes LINQ?

user1816120
la source
1
LINQ sert à interroger les graphiques d'objets. Il s'agit de Language INtegrated Query - il vous permet d'interroger et de manipuler des collections.
Oded
1
sa probablement une question fermable en l'état, il peut y avoir une bonne question qui se cache là-bas sur quels problèmes linq est un bon ajustement pour
jk.
1
Linq est déclaratif. Vous dites «ce que» vous voulez sans préciser «comment» c'est fait. Pour linq, cela signifie que vous pouvez utiliser une requête pour indiquer ce que vous voulez. Le code déclaratif peut être plus court et plus facile à comprendre pour certains problèmes.
mike30

Réponses:

16

LINQ est principalement conçu pour permettre des requêtes et des transformations fonctionnelles pures sur des séquences de données (vous remarquerez que toutes les extensions LINQ prennent des délégués Func mais pas des délégués Action). Par conséquent, le cas le plus courant d'une boucle qui ne correspond pas très bien à LINQ est celui qui concerne les effets secondaires fonctionnels non purs, par exemple

foreach(var x in list) Console.WriteLine(x);

Pour mieux utiliser LINQ, entraînez-vous simplement à l'utiliser.

Chaque fois que vous êtes sur le point d'écrire un forou une foreachboucle pour faire quelque chose avec une collection, arrêtez -vous, demandez-vous si cela convient bien à LINQ (c'est-à-dire qu'il ne s'agit pas seulement d'effectuer une action / un effet secondaire sur les éléments), et si c'est le cas, forcez-vous à écrire en utilisant LINQ.

Vous pouvez également écrire la foreachversion en premier, puis réécrire dans une version LINQ.

Comme le souligne svick, LINQ devrait viser à rendre votre programme plus lisible. Il est généralement bon dans ce domaine car il a tendance à souligner l'intention du code plutôt que le mécanisme; cependant, si vous trouvez que vous ne pouvez pas rendre vos requêtes plus lisibles qu'une simple boucle, n'hésitez pas à vous en tenir à la boucle.

Si vous avez besoin d'exercices pour vous entraîner, la plupart des exercices de programmation fonctionnels correspondront bien à LINQ, par exemple 99 problèmes (en particulier les 20 premiers environ) ou au projet euler .

jk.
la source
Je devrais peut-être supprimer cette question maintenant. Le modérateur a fait remarquer que cela ne convient pas à la communauté. Si vous pensez le contraire, veuillez me le dire.
user1816120
1
J'ajouterais que si vous le réécrivez dans LINQ et que l'original est encore plus lisible, conservez l'original et supprimez la version LINQ. Parfois, LINQ n'ajoute rien.
svick
@svick en théorie oui, je ne suis pas sûr de pouvoir en trouver des exemples;)
jk.
1
@jk. Par exemple, ReSharper propose parfois de convertir ma boucle en LINQ en utilisant Aggregate(). Je pense que la plupart du temps, la boucle est plus lisible.
svick
@svick est probablement un problème de ce à quoi vous êtes habitué, bien que j'admette que l'agrégat est un nom maladroit pour fold
jk.
1

Pour répondre à la question éditée: en bref, il est avantageux d'utiliser LINQ chaque fois que vous devez implémenter une fonctionnalité de "requête" (c'est ce que signifie le Q dans LINQ). La définition d'un domaine exact est difficile, mais elle simplifie considérablement une variété de tâches associées à l'extraction et à la manipulation de données à partir de collections.

Pour élaborer un peu, de nombreuses fonctionnalités de requête ont été introduites directement dans le langage (ou plutôt, les différents implémenteurs LINQ), donc des choses comme les agrégations, l'ordre, le regroupement, le filtrage, les projections, les jointures (et bien d'autres) sont toutes gérées pour vous. Les solutions basées sur LINQ sont également généralement beaucoup plus courtes que si vous les implémentiez "à la main", et communiquent également beaucoup mieux leur intention.

Un exemple simple qui aide souvent à transmettre la puissance de LINQ est d'afficher le contenu d'un répertoire, groupé par extension. Exécutez une mise en œuvre impérative typique dans votre tête - il y aura déjà beaucoup de détails de mise en œuvre au début. Peut-être utiliserons-nous un Dictionary<String, List<String>>pour indexer les fichiers par extension. Bien sûr, nous devrons vérifier si une clé existe déjà, instancier une liste, y ajouter, etc. Cela pourrait aller quelque chose comme:

Dictionary<string, List<string>> fileGroups = new Dictionary<string, List<string>>();

foreach (string file in Directory.GetFiles(Environment.CurrentDirectory))
{
    string extension = Path.GetExtension(file).ToLower();

    if (!fileGroups.ContainsKey(extension))
    {
        fileGroups[extension] = new List<string>();
    }

    fileGroups[extension].Add(file);
}

Considérez l'équivalent LINQ:

var query = from file in Directory.GetFiles(Environment.CurrentDirectory)
            group file by Path.GetExtension(file).ToLower();

Notez que la requête elle-même n'est que de 2 lignes, certainement plus courte que toute solution impérative que nous aurions pu trouver. Il est également assez lisible; le rapport signal / bruit est plus élevé qu'il ne l'était avec la première solution. Pour ceux qui sont nouveaux dans LINQ, vous devez générer les résultats de cette requête comme suit:

foreach (var fileGroup in query)
{
    Console.WriteLine(String.Format("*** Files with extension: {0}", group.Key));

    foreach (string file in fileGroup)
    {
        Console.WriteLine(file);
    }
}

Avec des exemples plus complexes, les différences deviennent normalement encore plus importantes (envisagez simplement le regroupement par plusieurs champs, par exemple). Donc, pour résumer, LINQ résout de nombreux problèmes d'interrogation de données "au jour le jour" d'une manière qui est souvent plus courte et plus auto-descriptive. Cela vient à un faible coût d'avoir à apprendre la syntaxe et la technologie, mais les avantages l'emportent largement sur les négatifs.

Daniel B
la source
Classez-vous la carte ou le pli comme "requêtes"? Je ne le sais pas vraiment mais je suppose que je pourrais le voir peut-être .. Je penserais normalement à un agrégat à la suite d'un calcul, pas à une "requête"
Jimmy Hoffa
@JimmyHoffa Je fais principalement référence à l'application du calcul à la collection sous-jacente, pas nécessairement au calcul lui-même. Mais il y a probablement des trous béants dans mon analogie, c'est censé être illustratif plutôt que 100% correct.
Daniel B
@JimmyHoffa non, mais je ne suis pas sûr qu'il existe une définition stricte de ce qu'est une requête pour commencer
jk.
0

Différents langages ont été développés au fil du temps pour les différents types de sources de données, par exemple SQL pour les bases de données relationnelles et XQuery pour XML. Par conséquent, les développeurs ont dû apprendre un nouveau langage de requête pour chaque type de source de données ou format de données qu'ils doivent prendre en charge. LINQ simplifie cette situation en offrant un modèle cohérent pour travailler avec des données sur différents types de sources et de formats de données. Dans une requête LINQ, vous travaillez toujours avec des objets. pour plus d'informations, visitez http://msdn.microsoft.com/en-us/library/bb397906.aspx

Rabbil
la source
Exactly LINQ est une API d'abstraction pour travailler avec des collections. Quelques avantages importants: en utilisant C #, vous obtenez STATIC! Vérification de vos requêtes et transformations
AndreasScheinert