linqref

Petit tour d’horizon de LINQ

LINQ, c’est quoi ?

LINQ signifie Language Integrated Query, soit langage de requêtage intégré. C’est donc un ensemble de mots clés et de méthodes permettant d’écrire des requêtes proches du SQL sur n’importe quel type de collection de données (List, XML, Base de données…), avec intellisense (le système d’auto-complétion intégré à Visual Studio), et la possibilité d’utiliser n’importe quelle classe / méthode de votre programme ou du framework.

Comment utiliser LINQ

Tout d’abord, LINQ n’est apparu qu’avec le Framework 3.5. Donc sans celui-ci et Visual Studio 2008, oubliez.
Il est également nécessaire d’ajouter une référence vers la DLL System.Core.

Ensuite, il vous faut utiliser l’espace de nom « System.Linq ».

using System.Linq;

Une simple requête

Commençons par créer un tableau d’entiers :

int[] monTableau = {1, 9, 6, 7, 52, 543, 4864, 120, 904, 41, 67, 4};

Si l’on voulait, en SQL, récupérer toutes les valeurs, on aurait une requête du genre :

SELECT * FROM monTableau

En LINQ, on obtient ça (notez que la requête ne sert – pour l’instant – à rien, puisqu’on récupère tel quel le tableau qu’on a) :

var resultat = from element in monTableau select element;

Si je traduits, ça fait : pour chaque element dans monTableau, je prend tout l’element.
Le mot-clé var, valable uniquement lors d’une déclaration avec initialisation, permet de créer la variable (en l’occurrence resultat) du type renvoyé par la partie à droite du =.
Les requêtes Linq renvoient toujours une collection d’éléments du type de ce que vous avez derrière le select (en l’occurrence, le type de element, donc int).

La clause where

Elle sert à la même chose qu’en SQL : filtrer les résultats. Sauf que la syntaxe est une syntaxe conditionnelle C# classique.

var resultat1 = from element in monTableau where element % 2 == 0 select element;
var resultat2 = from element in monTableau where element < 100 select element;
var resultat3 = from element in monTableau where element > 10 && maFonction(element) select element;

Là, on récupère respectivement

  • Tous les nombres pairs de monTableau
  • Tous les nombres de monTableau inférieurs à 100
  • Tous les nombres supérieurs à 10 pour lesquels la méthode maFonction renvoie true

La clause orderby

Elle sert à trier les éléments.

var resultat = from element in monTableau orderby element descending select element;

Le résultat contiendra donc les nombres triés du plus grand au plus petit. Pour trier dans l’autre sens, il faudrait simplement enlever le mot clé « descending ».

La clause select

La requête renverra une liste de ce que vous placez dans le select.

var resultat1 = from element in monTableau select element + 1;
var resultat2 = from element in monTableau select element.ToString();
var resultat3 = from element in monTableau select "Le nombre " + element.ToString();
var resultat4 = from element in monTableau select new MaClasse(element);

On a donc respectivement :

  • Les éléments incrémentés de 1
  • Une collection de string des nombres
  • Une collection de string du genre « Le nombre 1″, « Le nombre 9″…
  • Une collection d’objets de type MaClasse, initialisés avec le constructeur prenant comme argument l’element

Mais il est aussi possible d’utiliser les types anonymes. Il s’agit tout simplement d’un type que vous ne définissez que lorsque vous remplissez le tableau.

var resultat = from element in monTableau select new { Nombre = element, Taille = element.ToString().Length };

Ainsi, on récupère une collection d’objets avec deux propriétés : une propriété Nombre, qui contient l’élément lui-même et une propriété Taille, qui contient le nombre de chiffres de l’élément.

Se connecter à n’importe quelle base de données

Les bases de données sont essentielles pour une grande partie des applications. Cependant, entre les différentes bases de données existantes (SQL Server, MySQL, SQLite, Access, Oracle…), la chaine de connexion sera différente et il sera nécessaire d’avoir le bon driver.
Un seul site pour trouver tout ça : ConnectionStrings.com

Global Assembly Cache

Accéder « normalement » au GAC

Pour ceux qui ne le sauraient pas, le GAC (Global Assembly Cache) est un dossier, sous Windows, dans lequel on peut installer ses DLL partagées.
Ce répertoire se trouve dans C:\Windows\assembly.
Global Assembly Cache
En allant dans ce répertoire, vous vous rendez compte que la mise en page est spéciale. En effet, impossible, par exemple, d’avoir les propriétés des DLL (comme par exemple la date de modification…). Pourtant, le GAC est un dossier comme un autre avec des fichiers comme d’autres. Voici donc une astuce pour l’afficher « normalement ».

  • Allez dans le poste de travail
  • Allez dans Outils → Connecter un lecteur réseau…
  • Choisissez une lettre pour le lecteur
  • Comme dossier, choisissez \\127.0.0.1\C$\Windows\Assembly
  • Ouvrez le lecteur nouvellement créé et le tour est joué
separator

Créer un Separator avec WinForms

Vous êtes en train de dessiner votre fenêtre WinForms et vous cherchez désespérément le contrôle « Separator » ? Si ce contrôle n’existe pas, de base, il existe une méthode extrêmement simple pour avoir un effet identique.

Il s’agit simplement de créer un Label avec les propriétés suivantes :

Label separator = new Label();
separator.Height = 2;
separator.Text = string.Empty;
separator.AutoSize = false;
separator.BorderStyle = BorderStyle.Fixed3D;

Il ne reste plus qu’à choisir la valeur de Width pour la largeur du séparateur et à placer le contrôle où vous le souhaitez.
Si vous préférez avoir un séparateur vertical, il suffit de mettre Width à 2 et Height à la hauteur de votre choix.

Lever un événement dans une classe fille

Pour lever un événement dans une classe, c’est très simple :

// On le déclare
public event EventHandler monEvenement;

// Puis dans une méthode quelconque
public void MaMethode()
{
    // On regarde s'il y a des méthodes abonnées
    if (monEvenement != null)
    {
        // Et on lève l'événement
        monEvenement(new Object(), EventArgs.Empty);
    }
}

Mais si l’on associe l’héritage à tout cela :

class Mere
{
    public event EventHandler monEvenement;
}

class Fille : Mere
{
    void MaMehtode()
    {
        if (monEvenement != null) monEvenement(new Object(), EventArgs.Empty);
    }
}

on a droit à l’erreur de compilation suivante : L’événement ‘<Mere.monEvenement>’ ne peut apparaître qu’à gauche de += ou -= (sauf en cas d’utilisation à partir du type ‘<Mere>’)

La solution est toute simple : passer par une méthode intermédiaire.

class Mere
{
    public event EventHandler monEvenement;

    // Evidemment, cette méthode doit être protected pour que les classes filles puissent y accéder
    protected void RaiseMonEvenement(object sender, EventArgs e)
    {
        if (monEvenement != null) monEvenement(sender, e);
    }
}

class Fille : Mere
{
    void MaMethode()
    {
        // En plus, il n'y a même pas besoin de vérifier qu'il y a bien des méthodes abonnées à l'événement
        // (la vérification étant directement faite dans la classe mère)
        RaiseMonEvenement(new Object(), EventArgs.Empty);
    }
}