Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Votre compte Gmail est-il piraté ?

Gmail, paradis et enfer tout à la fois. Paradis de disposer d'un compte mail ubiquitaire disponible de partout tout le temps, de bénéficier d'archives totales sur des années. Enfer du courrier privé et confidentiel accessible depuis partout avec un simple login, enfer de violation de la vie privée lorsque Gmail lui-même lit vos mails pour mieux cibler la pub qu'il affiche à côté pendant que vous les consulter... Mais le risque le plus grand est bien entendu que quelqu'un d'autre lise vos mails.

Avec un système de type Outlook, pas de problème, tout est sans cesse téléchargé sur votre PC et toute indiscrétion suppose que l'indélicat puisse accéder à votre machine en votre absence. A vous de mettre des mots de passe qui la protège et l'affaire est jouée. Mais avec Gmail ?

Histoire certainement de nous faire oublier qu'ils violent eux-mêmes notre intimité en lisant nos mails pour afficher des pubs ciblées, Gmail vient de mettre en place un système permettant de vérifier les accès à son compte.

Regardez tout en bas de l'écran, sous l'indication de votre utilisation de l'espace disque :

En cliquant sur "Details" vous obtiendez un écran vous permettant de voir les IP des derniers accès avec l'heure mais vuos pourrez aussi couper immédiatement l'accès à toutes les IP différentes de celle de la machine sur laquelle vous êtes. Utile au bureau si on a laissé sa page Gmail ouverte sur une autre machine 2 étages plus haut, pratique pour vérifier que personne n'a piraté votre compte (consultation depuis des hot spots publiques par exemple), etc.

Voici la capture de l'écran de détail :

 

Amis paranos, bonne journée !

Et.. Stay Tuned !

Comment passer outre la limitation du DISTINCT sur un SELECT contenant un champ text sous SQL Server

Voici un billet moins "hi-tech" que d'habitude. Point de LINQ dans tout çà, juste un bon server SQL SERVER, une table contenant un champ Text ou NText et une bête requête qui peut retourner plusieurs fois le même enregistrement. Et comme on ne désire pas voir les copies éventuelles, bien entendu on place instinctivement une clause DISTINCT dans le SELECT.

C'est beau, simple comme SQL... Sauf que... SQL Server n'aime pas du tout la clause DISTINCT s'il y a un champ texte dans le SELECT. Et pour cause, il ne sait pas comment comparer les contenus, du coup point de DISTINCT possible.

Quelques bonnes âmes vous conseilleront peut-être :

a) de changer tous vos champs texte en varchar
b) de vous passer du champ texte dans le SELECT et de l'obtenir à part dans une autre requête

Les conseilleurs ne sont pas les codeurs ! Les varchar ont une limite de 8000 caractères et il n'est pas toujours possible de les substituer à Text/NText. De plus modifier tous les champs de ce type dans une application peut être un énorme travail (code, procédures stockées, vues, tout cela à mettre à jour). Solution bidon donc.

Quant à faire le SELECT DISTINCT sans les champs texte puis à faire une seconde requêtre derrière pour les obtenir, c'est franchement lourd et pas forcément sans conséquence sur le code appelant (qui doit faire autant de sous requêtes que de records pour obtenir les champs texte, et les stocker, etc).

Non, il existe plus simple, et un peu plus vicieux : faire une jointure de la table sur elle même.

Oui, tout simplement. L'astuce consiste à faire un select dans la table de tous les champs (y compris les champs texte) mais sans la clause DISTINCT, table qu'on lie à elle même mais ce coup ci en faisant un SELECT DISTINCT qui lui omet les champs texte... La feinte est bonne, mais elle ne saurait faire de miracle, en effet, les champs texte ne seront pas utilisés pour faire la DISCTINCTion entre les records. Cette solution n'a donc qu'un seul hic : elle ne peut pas fonctionner si vous voulez vraiment que le DISTINCT prenne en compte les champs texte. Là je n'ai pas vraiment d'astuce à vous proposer. Mais pour les autres, voici un bout de code SQL fictif qui vous montrera la syntaxe à utiliser :

SELECT t1.c1, t1.c2, t1.LeChampTexte
FROM MaTable t1 JOIN
     (SELECT DISTINCT c1,c2 FROM MaTable WHERE Desc LIKE 'Test%') AS t2
     ON t1.c1 = t2.c1

on suppose ici que le champ "c1" représente la clé (il peut s'agir de plusieurs champs, of course, à vous d'adapter le code), que le champ "c2" est un autre champ sur lequel le DISTINCT portera et que "LeChampTexte" ... est le champ texte qui pose problème. On voit mieux ici que le DISTINCT ne sera effectué que sur "c1" et "c2". Mais cela permet bien de faire un DISTINCT tout en retournant les champs texte, le tout en une seule requête...

Bon SQL et... Stay Tuned !

Un cadeau à télécharger : des exemples LINQ !

Dernièrement je vous parlais des "101 exemples LINQ" publiés par Microsoft et je vous donnais les liens vers la page Web de ces derniers ainsi que vers un téléchargement d'une application complète distribuée avec la Ctp de mars 2007.

Hélas, qu'il s'agisse du site Web ou bien de l'appli en question, le code n'est pas tout à fait fonctionnel. On peut toujours le lire pour regarder les exemples de syntaxe LINQ mais il est quand même plus agréable de disposer d'une application qui marche pour tester.

A l'époque de la sortie des "101 exemples" j'avais commencé à me bricoler une application. En partant des exemples publiés sur le site Web j'avais construit une appli de test "laboratoire" pour expérimenter des tas de choses pas forcément liées à LINQ. Quand j'ai étudié plus tard l'exemple MS de la Ctp de mars 2007 je me suis aperçu que face aux mêmes problèmes le concepteur de cette dernière et moi avions finalement trouvé des solutions très proches. Et comme la version MS gérait deux ou trois choses que je n'avais pas implémentées j'ai décidé, en raison des ressemblances des codes, de les fusionner en une application simple et fonctionnelle.

Ce week-end le temps n'étant pas vraiment à la baignade (l'eau est bonne mais le vent de nord... qui interdit d'aller à la pêche aussi...) j'ai ressorti ce projet que j'avais laissé dans un coin de disque. je l'ai dépoussiéré et finalisé pour être utilisable. Il a profité de ce nettoyage d'hiver (ah bon ? c'est l'été ?) puisque cela a permis de le reprendre sous VS 2008 SP1 alors que ma version originale tournait sous la bêta. Au passage cela m'a permis de vérifier la bonne tenue de route de Resharper 4.0 qui gère vraiment bien les nouveautés de C# 3.0 et de LINQ (je vous en parlais aussi dernièrement).

Le code est téléchargeable ici (code source + l'exécutable dans bin/debug) : Linq101.rar (488,53 kb)

Une petite image de l'interface pour la route :

Bon téléchargement,

et ... Stay Tuned !

L'outil le plus intelligent enfin à jour ! (Resharper 4.0)

Resharper, si vous ne connaissez pas c'est que vous ne développez pas sous .NET ! C'est en effet un add'in incroyablement intelligent et indispensable une fois qu'on l'a essayé.

Il apporte à Visual Studio (depuis VS 2003) les petits plus qui transforment cet excellent IDE en une bombe proche de la perfection. Personnellement je ne peux plus m'en passer depuis longtemps.

Il y avait toutefois un bémol avec VS 2008, même si la version 3.1 était bien intégrée à l'IDE, elle ne savait pas gérer les dernières nouveautés du langage comme LINQ par exemple (oui encore LINQ...) ce qui gâchait le plaisir et obligeait à déconnecter bon nombre des features de Resharper lorsqu'on abordait un code plein de requêtes LINQ, d'expressions Lambda et autres derniers bijous syntaxiques.

Mais enfin tout est rentré dans l'ordre !

Avec un peu de retard sur la sortie de C# 3.0 (masi quel boulot le concepteur a du fournir !) la version 4.0 de Resharper est enfin disponible. Elle ajoute plein de nouvelles possibilités à cet outil déjà très complet mais, Ô comble de la satisfaction enfin retrouvée, elle gère parfaitement C# 3.0 et toutes ses nouvelles tournures, dont LINQ bien entendu.

A 199 tous petits dollars tous dévalués, pour la licence un développeur, c'est presque un cadeau et ça serait surtout une mesquinerie énorme que de ne pas se l'offrir (l'upgrade coûte encore moins cher si vous possédez une 3.0 et même une 2.0 pour VS 2003 me semble-t-il).

Pour ceux qui ne connaissent pas je ne vais pas détailler tout ce que Resharper fait déjà ni même les nouveautés de la 4.0, c'est trop long. Le mieux c'est que vous alliez directement sur le site de JetBrains et que vous regardiez de plus près les démos (fixes ou captures d'écrans animées flash).

N'oubliez pas aussi que Resharper supporte des plugins comme AgentSmith qui offre des contrôles supplémentaires comme par exemple la correction orthographique ou le contrôle des conventions de nommage (AgentSmith est gratuit, ce qui ne gâche rien).

Bon dev ...

... Et Stay Tuned !

Les 101 exemples de LINQ à portée de clic !

LINQ.. Je vous en parle très souvent car cela en vaut largement la peine. L'essayer c'est l'adopter, surtout que ses diverses moutures (Linq to XML, Linq to SQL, Linq to Object...) peuvent trouver leur place et rendre service dans tout type de développement.

Articles, astuces, j'ai beaucoup écrit sur LINQ et ce n'est certainement pas terminé. Mais il ne faudrait pas oublier les "101 exemples pour LINQ" créés par Microsoft.

A ma connaissance il n'existe pas de traduction, cela n'existe qu'en anglais. Mais c'est une belle visite de la syntaxe de LINQ et certainement un complément indispensable à une autoformation sur le sujet.

Ces exemples ne sont pas très récents mais je me suis rendu compte que peu de développeurs les connaissaient, au moins en France. D'où l'intérêt de rappeler leur existence.

Pour la petite histoire, le chef de projet qui a écrit ces exemples a touché $202 de la part de Anders... En effet, lorsqu'il a fallu écrire les exemples, Anders était assez pressé de voir le travail fini et avait promis $2 pour chaque exemple qui serait terminé à la dead-line, une sorte de plaisenterie. Le jour fatidique, arrivé en réunion, le chef de projet en avait réalisé 101. Anders a alors fouillé ses poches et a fait l'appoint, 101x2 = $202 qu'il a remis au gars un peu gêné, ne sachant s'il devait accepter ou pas... Ce bon chef de projet a utilisé la somme pour inviter le soir même les développeurs de son équipe au resto. Une belle histoire non ? :-)

PS: Vous pouvez aussi télécharger d'autres exemples Linq en cliquant ici [edit: en novembre 2012 le site pointé n'existe plus, sorry]. Ce n'est pas très récent (Ctp de mars 2007) mais pour ceux qui prennent Linq au vol plutôt qu'à ses débuts, il est fort probable, si vous êtes dans ce cas, que vous soyez passé à côté de ce téléchargement...

PS2: Si vous voulez faire tourner le code des 101 exemples LINQ, vous trouverez sur le site pointé par le lien donné en début d'article le code de la méthode GetProductList(). Ce code est assez exotique et ne compile pas. Il faut le modifier pour en tirer quelque chose. Pour vous simplifier la vous trouverez ci-après une unité de code C# contenant une définition correcte de cette fonction, encapsulée dans une classe abstraite. Cela devrait vous aider... Data.rar (2,26 kb)

Lé fotes d'ortografe ds les programs é lé page web c mauche !

Les fôtes d'ortografes dans les blogs, c courant, avec les sms les jeunes ne sav + écrir c connu.

Mouais... mais dans les applications c'est la tehon, disons-le franchement !

Et qui, ici, perd son temps à faire du copier coller de toutes les chaînes de caractères de son code pour les tester sous Word et les corriger ? Hein ? qui ? .... j'en étais sûr.

Je plaide coupable aussi d'ailleurs. Et c'est vraiment pas une bonne chose, car comme tout le monde, même en relisant j'en laisse passer des fautes.. On ne peut se concentrer sur le code qui implique logique et rigueur d'esprit et en même temps sur l'orthographe et la grammaire de notre langue, totalement illogique et sans rigueur d'esprit, je suis bien d'accord, je ne vous le fait pas dire. Mais quand même...

L'orthographe est sans nul doute la science des ânes, c'est la sagesse populaire qui le dit, mais les fautes dans les écrans des applications, qu'il s'agisse d'applis de bureau ou pire de pages Internet visibles par la planète bizarrement, et paradoxalement, ça ne vous fait pas passer non plus pour le plus brillant des intellectuels. C'est injuste je sais, mais c'est comme ça.

Il faut donc trouver une solution, simple et efficace qui ne réclame surtout pas trop de boulot à mettre en oeuvre, l'informaticien est fainéant, c'est connu (en tout cas les meilleurs, c'est presque un critère de sélection :-) ).

Si cette solution est gratuite c'est encore mieux (l'informaticien aime ce qui est gratuit, c'est aussi connu). Alors jetez un oeil sur IntelliSpell, un outil de Component One qui existe en version "community" gratuite. C'est ici, en cliquant ce lien. Un bémol tout de même, la version gratuite semble ne fonctionner qu'avec le dictionnaire US, quelle que soit la locale de votre Windows ou de VS 2008. J'ai demandé des précisions à Component One sur le sujet, mais visiblement ils ne sont pas pressés de répondre aux questions. Dommage. Mais l'outil reste intéressant à tester malgré tout.

Il existe bien entendu d'autres "spell checkers" pour Visual Studio, nommons sans ordre de préférence, à vous de voir :

  • StudioSpell
  • Arkhipov  [edit: en novembre 2012 le site ne propose plus ce lien, sorry]
  • Agent Smith (plugin gratuit pour Resharper)
  • et bien d'autres...

Si vous en connaissez un particulièrement bien, n'hésitez pas à l'indiquer en laissant un commentaire !

NB: ceux qui trouveront des fautes dans ce post auront gagné... le droit de se taire, on va pas jouer à ce jeu là hein, ça serait terriblement mesquin...Wink

Stay Tuned !

Quizz C#. Vous croyez connaître le langage ? et bien regardez ce qui suit !

C# est un langage merveilleux, plein de charme... et de surprises !

En effet, s'écartant des chemins battus et intégrant de nombreuses extensions comme Linq aujourd'hui ou les méthodes anonymes hier, il est en perpétuelle évolution. Mais ces "extensions" transforment progressivement un langage déjà subtile à la base (plus qu'il n'y paraît) en une jungle où le chemin le plus court n'est pas celui que les explorateurs que nous sommes auraient envisagé...

Pour se le prouver, 6 quizz qui vous empêcheront de bronzer idiot ou de vous endormir au boulot !

Un petit projet exemple avec les questions et les réponses sera téléchargeable en fin d'article demain...
[EDIT 4-7-08] Le lien se trouve désormais en fin d'article. Le code source contient les réponses au quizz.

Quizz 1

Etant données les déclarations suivantes :

class ClasseDeBase
{
   
public virtual void FaitUnTruc(int x)
    {
Console.WriteLine("Base.FaitUnTruc(int)"); }
}

class ClasseDérivée : ClasseDeBase
{
   
public override void FaitUnTruc(int x)
   { Console.WriteLine("Dérivée.FaitUnTruc(int)"); }

   public void FaitUnTruc(object o)
  {
Console.WriteLine("Dérivée.FaitUnTruc(object)"); }
}

Pouvez-vous prédire l'affiche du code suivant et expliquer la sortie réelle :

    ClasseDérivée d = new ClasseDérivée();
    int i = 10;
    d.FaitUnTruc(i);

Gratt' Gratt' Gratt'.....

Quizz 2

Pouvez-vous prédire l'affichage de cette séquence et expliquer l'affichage réel ?

double d1a = 1.00001;
double d2a = 0.00001;
Console.WriteLine((d1a - d2a) == 1.0);

double d1b = 1.000001;
double d2b = 0.000001;
Console.WriteLine((d1b - d2b) == 1.0);

double d1c = 1.0000001;
double d2c = 0.0000001;
Console.WriteLine((d1c - d2c) == 1.0);

Je vous laisse réfléchir ...

Quizz 3

Toujours le même jeu : prédire ce qui va être affiché et expliquer ce qui est affiché réellement... c'est forcément pas la même chose sinon le quizz n'existerait pas :-)

List<Travail> travaux = new List<Travail>();
Console.WriteLine("Init de la liste de delegates");
for (int i = 0; i < 10; i++)
{ travaux.Add(
delegate { Console.WriteLine(i); }); }

Console.WriteLine("Activation de chaque delegate de la liste");

foreach (Travail travail in travaux) travail();

 Les apparences sont trompeuses, méfiez-vous !

Quizz 4

Ce code compile-t-il ?

public enum EtatMoteur { Marche, Arrêt }

public static void DoQuizz()
{
   
EtatMoteur etat = 0.0;
   
Console.WriteLine(etat);
}

Quizz 5

 Etant données les déclarations suivantes :

private static void Affiche(object o)
{
Console.WriteLine("affichage <object>"); }

private static void Affiche<T>(params T[] items)
{
Console.WriteLine("Affichage de <params T[]>"); }

 Pouvez-vous prédire et expliquer la sortie de l'appel suivant :

  Affiche("Qui va m'afficher ?");

 Je sens que ça chauffe :-)

Quizz 6

 Etant données les déclarations suivantes :

 delegate void FaitLeBoulot(); private static FaitLeBoulot FabriqueLeDélégué()
{
  
Random r = new Random();
  
Console.WriteLine("Fabrique. r = "+r.GetHashCode());

  
return delegate {
                           
Console.WriteLine(r.Next());
                           
Console.WriteLine("delegate. r = "+r.GetHashCode());
                         };

}

 Quelle sera la sortie de la séquence suivante :

    FaitLeBoulot action = FabriqueLeDélégué();
    action();
   
action();

 

Conclusion

C# est un langage d'une grande souplesse et d'une grande richesse. Peut-être qu'à devenir trop subtile il peut en devenir dangereux, comme C++ était dangereux car trop permissif.

Avec C#, même de très bons développeurs peuvent restés interloqués par la sortie réelle d'une séquence qui n'a pourtant pas l'air si compliquée.
Ses avantages sont tels qu'il mérite l'effort de compréhension supplémentaire pour le maîtriser réellement, mais tout développeur C# (les moyens comme ceux qui pensent être très bons!) doit être mis au moins une fois dans sa vie face à un tel quizz afin de lui faire toucher la faiblesse de son savoir et les risques qu'il prend à coder sans vraiment connaître le langage.

Comme toujours l'intelligence est ce bel outil qui nous permet de mesurer à quel point nous ne savons rien.
Nous sommes plutôt habitués à envisager cette question sous un angle métaphysique, le développement nous surprend lorsque lui aussi nous place face à cette réalité...

Pour le projet exemple dont le source contient les réponses cliquez sur le lien en fin de billet.

So (et plus que jamais!) .. Stay Tuned !

Quizz.rar (103,41 kb)

Halte aux arnaques !

Tiens, encore un coup de gueule... C'est le printemps pourri et le début d'été moyen qui doit me faire ça...

Juste une info pour que vous ne vous fassiez pas avoir aussi. Il s'agit d'ampoules à basse consommation, un sujet d'actualité s'il en est.

J'ai acheté chez mon Intermaché local des ampoules basses consommation de marque "GF", pas trop chères certes mais un produit vendu en France doit légalement être fonctionnel. Devant la piètre qualité de l'objet en question (éclairage de mauvaise qualité transformant la meilleure des frimousses bronzées en teint de mort vivant, et surtout durée de vie exceptionnellement courte), je me suis amusé à vérifié l'amballage.

Tout est faux, truqué. Notamment le produit se présente avec le logo de l'UKAS, un organisme de certification, ainsi qu'avec un logo ISO 9001. Je me suis donc intéressé au logo UKAS et ai demandé à cet organisme basé chez les Grands Bretons de me confirmer la conformitié de leur logo.

Il s'agit d'un faux, d'une immitation grossière (je dispose bien entendu des mails échangés avec l'UKAS ainsi que des photos que je leur ai transmises).

L'UKAS va donc mener une action en direction de l'importateur, et sans présager de celle-ci ni de ses résultats je tenais à vous dire de vous méfier de ce produit en particulier, importé par la société "Balestrini" en France (adresse complète en fin de billet) et de tous ces produits bidons qui affichent des faux logos de certification ou de qualité.

Méfiez-vous, contrôlez, n'hésitez pas à écrire aux organismes en question, ils répondent vite et de façon courtoise. On leur rend service en dénonçant les faux, et surtout on protège les consommateurs que nous sommes qu'on prend trop facilement pour des crétins.

Voici l'objet du délit, ce produit là, si vous le reconnaissez, au moins ne l'achetez pas... Et méfiez aussi de tout ce qui est importé ou fabriqué par "Balestrini", les certifications qu'ils affichent sur leurs produits sont des faux. Vous pourrez aussi rigoler franchement en découvrant la photo d'une Alim de PC que j'ai placée il y a longtemps dans les pages de ce blog (cliquez ici pour voir la "chose"). Il s'agit d'une pratique illégale hélas répandue. Restez vigilants !

L'importateur peu scrupuleux : 

"BALESTRINI"
22, rue de la Haye
38070 Saint-Quentin-Fallavier, France

APE :  code 2219Z "Fabrication d'autres articles en caoutchouc" (les lampes et leur importation ça rendre là dedans ??)
forme juridique : "SARL"
Capital: 7500 euros 
CA 2007 : 650 000 euros
Gérante: Ms DEHEE Marie-Paule (née BASLESTRINI) le 19-3-1966

Un extrait de la réponse de l'UKAS :

"The logo in question is not a UKAS logo.  However, it would appear to be a crude attempt at a copy of the UKAS Quality Management logo.  This logo is issued by UKAS to certification bodies once they have achieved UKAS accreditation.  The UKAS Quality Management logo should never be displayed on products as it has no bearing on the quality of the product.  Accredited certification bodies can sub-licence the use of the UKAS quality management logo to any client that they have certificated to ISO 9001 but it must be displayed in the same box as their own logo (the certification body's) and have the UKAS accreditation number of the issuing certification body underneath it.
 
The samples attached to your email are somewhat unsophisticated copies to say the least, to the extent that the word 'Management' is shown as 'Masagement'.
  "

Le contact que j'ai eu à l'UKAS (pour éviter le spam je ne met pas son mail, si vous le voulez je vous le donnerai, contactez moi):

Ms Kayleigh Freeman
Business Information Administrator
United Kingdom Accreditation Service
21-47 High Street
Feltham
Middlesex
TW13 4UN
Direct Dial: 020 8917 8507
Fax: 020 8917 8500

Adios XP !

Et oui, nous sommes le 1er juillet et nous entrons dans une ère nouvelle, depuis ce matin XP ne peut plus être acheté en magasin...

Microsoft prévoit quelques dérogations de ci de là et a repoussé la fin du support à 2014 au lieu de 2009.

Mais il va falloir s'y faire, l'OS d'un PC s'appelle Vista, plus XP. A moins de passer à Linux, réponse extrême et peu rentable puisque dans ce cas ce ne sont pas quelques incompatibilités avec les programmes qu'on possède qu'il faudra gérer, mais une incompatibilité totale...

Il n'en reste pas moins vrai que XP a été la première version de Windows aussi complète et aussi stable. Ceci explique cela puisque c'est aussi celle qui a connu la durée de vie la plus longue sur le marché.

C'est donc bien une époque qui s'achève et une autre qui commence.

O'lé com'tche !*

(* "c'est comme çà !" en patois charentais :-) )

De toute façon toutes les machines récentes sont livrées avec Vista et seuls les possesseurs de dinosaures (machines de plus d'un an donc en jargon d'informaticien) auront à gérer la transition... Pour ma part la machine spécialisée pour le Home Studio restera en XP, mes portables sont déjà sous Vista et ma machine principale est en double boot XP/Vista, la question est donc réglée depuis un moment  :-)

Hasta la .. Vista !

Linq au quotidien, petites astuces et utilisations détournées...

Linq je vous en parle souvent, c'est tellement génial. Et ce que j'aime bien c'est trouver des utilisations presque à contre-sens de Linq.
J'entends par là des façons de "rentabiliser" Linq à toute autre tâche que d'interroger des données (SQL, XML ou autres).

Je ne suis pas le seul dans ce cas ! J'ai au moins trouvé un autre zigoto qui s'amuse au même jeu, Igor Ostrovsky dont vous pouvez visiter le blog (cliquez sur son nom). Comme il s'exprime en anglais et que je sais que certains visiteurs ici ne sont pas forcément doués pour cette langue, voici une adaptation libre(*) de son billet présentant quelques astuces très amusantes.
(*) je n'ai repris que les exemples de code, le texte et le projet exemple sont de mon cru, si vous parlez anglais je vous laisse découvrir la prose de Igor sur son blog.

Initialiser un tableau, une liste

Il est souvent nécessaire d'initialiser une array avec des éléments qui, pour que cela soit utile, répondent à certains critères. Normalement cela se règle soit sous la forme d'une liste de constantes dans la déclaration de l'array, ce qui est pour le moins assez peu souple, soit sous la forme d'un code d'initialisation, ce qui du coup devient assez lourd pour parfois pas grand chose... C'est oublier que Linq peut apporter ici une aide non négligeable !

Voici trois exemples :

int[] A = Enumerable.Repeat(-1, 10).ToArray();
int[] B = Enumerable.Range(0, 10).ToArray();
int[] C = Enumerable.Range(0, 10).Select(i => 100 + 10 * i).ToArray();

Les trois arrays contiendront 10 éléments. "A" contiendra 10 éléments tous égaux à -1. "B" contiendra la suite 0 à 9, et "C" contiendra la suite de 100 à 190 par pas de 10.

Amusant, n'est-il pas ?

Plusieurs itérations en une seule

Imaginons que nous possédions deux arrays, A1 et B2, chacune contenant une sélection différente d'éléments. Supposons que souhaitions appliquer le traitement "Calcule(x)" aux éléments de ces deux arrays. La solution s'imposant serait :

foreach (var x in A1) { Calcule(x); }
foreach (var x in A2) { Calcule(x); }

Ce n'est pas très long, mais répéter du code n'est jamais très élégant. Voici comme Linq permet de faire la même chose en une seule boucle :

foreach (var x in A1.Concat(A2)) { Calcule(x); }

L'opérateur Concat effectue une .. concaténation, donnant l'illusion à notre boucle qu'elle travaille sur une seule et même array alors qu'il n'en est rien... On notera que Linq travaillant au niveau des énumérateurs, il n'y même pas de variable temporaire créée par le mécanisme pour stocker la concaténation. C'est élégant et en plus c'est efficace du point de vue de la mémoire.

Fun, isn't it ?

Créer des séquences aléatoires

Il est parfois nécessaire de créer des séquences aléatoires, pour tester un bout de code par exemple. La classe Random est bien pratique mais encore une fois il faudra déclarer le tableau puis déclarer une méthode pour l'initialiser en utilisant Random. Avec Linq tout cela peut se réduire à deux déclarations :

Random rand = new Random();
var ListeAléatoire = Enumerable.Repeat(0, 10).Select(x => rand.Next(10,500));

Le tableau "ListeAléatoire" contiendra 10 nombres aléatoires entre 10 et 500, et pas une seule déclaration de méthode à l'horizon. Vous noterez en revanche l'utilisation qui est faite de l'expression Lambda (nouveauté de C# 3.0) au niveau du Select.

Créer des chaînes de caractères

Si les exemples portent jusqu'ici sur des tableaux de nombres, c'est par pure souci de simplification. Il est bien entendu possible d'appliquer les mêmes astuces à d'autres types de données comme les chaînes :

 string chaine = new string( Enumerable.Range(0, 20) .Select(i => (char)(‘A’ + i % 3)) .ToArray());

La chaîne "chaine" contiendra "ABCABCABCABCABCABCAB". Remplacez le "20" par un "rand.Next(10,100)" par exemple, et en plus la longueur de la chaîne sera elle-même aléatoire. C'est pas pratique ça ?

Dans les commentaires du blog de Igor, un lecteur proposait une autre façon d'initialiser une chaîne avec Linq, la voici pour l'intérêt de la démonstration de la versatilité de Linq :

string chaine2 = string.Join(string.Empty, Enumerable.Repeat("ABC", 7).ToArray());

Ici on peut passer une pattern et un nombre de répétition.

Convertir une valeur en séquence de 1 objet

Il est parfois nécessaire de convertir une valeur en une séquence de longueur 1. Passer un paramètre unique là où un tableau de valeur est attendu réclame de créer le fameux tableau et de l'initialiser. Rien de bien méchant mais pourquoi ne pas mettre Linq à contribution ?

IEnumerable<int> sequence = Enumerable.Repeat(LaValeur, 1);

La répétition de 1 élément peut sembler être une sorte de contresens, mais si les concepteurs de la fonction partageaient cette opinion n'auraient-ils pas levé une exception pour toute valeur inférieure à 2 ... :-)
C'est en tout cas un moyen bien pratique d'arriver au résultat souhaité en une seule opération !

Enumérer tous les sous-ensembles d'un tableau

Il s'agit plus ici d'un "plaisir pervers" que d'une réelle utilité quotidienne il faut l'avouer, mais pour l'intérêt de la syntaxe voici comment énumer tous les sous ensembles d'un tableau (attention, si la taille du tableau dépasse quelques dizaines d'éléments le temps de calcul peut vite exploser ...) :

T[] tableau = …;
var subsets = from m in Enumerable.Range(0, 1 << tableau.Length)
              select
                  from
i in Enumerable.Range(0, tableau.Length)
                  where (m & (1 << i)) != 0
                  select arr[i];

Je vous laisse réfléchir à la syntaxe, peu évidente de prime abord, et le côté un peu "tordu" de cette astuce, mais elle répond à un besoin qui l'est tout autant. Et Linq peut aussi servir à cela.
Quelques clés pour comprendre : la requête ne retourne pas des items de "tableau" mais bien des sous ensembles de "tableau", c'est à dire des tableaux. Chaque tableau contient une combinaison unique d'éléments de "tableau". Si vous prenez tableau = B de notre premier exemple (c'est à dire la suite d'entiers 0 à 9), la requete Linq ci-dessus retournera 1024 sous-ensembles. Avouez que bien qu'un peu difficile à comprendre à première lecture, le procédé est d'une grande élégance... (Vous pouvez regarder le fonctionnement de cette requête de plus près grâce au projet démo téléchargeable en fin d'article).

Un peu de code...

Pour mieux comprendre les choses il est toujours préférable de faire tourner un bout de code. J'y ai pensé ! Vous trouverez un projet console complet plus bas ;-)

Conclusion

Igor montre au travers de ces différentes utilisations de Linq ce que je tente aussi de vous montrer dans mes billets : Linq est d'une grande souplesse, Linq ne se limite pas à faire du SQL en C#, Linq est un atout majeur pour le développeur qui sait s'en servir au quotidien. Initialiser un tableau, convertir un tableau dans un type différent, jouer sur les combinatoires, fabriquer des chaînes de caractères ou des séquences aléatoires de test, etc, etc. Il n'y a pas un bout de code dans lequel il ne soit possible de glisser un peu de Linq pour le rendre plus sobre, plus élégant et souvent plus performant.
Remercions Igor pour ces exemples de code (seule chose reprise de son billet, j'ai mon propre style, il a le sien :-) )

Le code complet

LinqFun.rar (99,18 kb)

Bonus 

Mitsu, qu'on ne présente plus, ça serait faire insulte à sa notoriété !, a proposé il y a quelques temps déjà une autre astuce Linq tout à fait amusante, elle consiste à obtenir la décomposition d'un nombre en facteurs premiers au travers de requêtes Linq et d'un class helper permettant d'écrire : 144.ToPrimeNumbersProduct() et d'obtenir en sortie "2^3 * 3^2 * 7". Je vous en conseille la lecture en suivant ce lien.