Comme vous le savez tous, je suis quelqu'un qui apprécie particulièrement le partage de code source, et donc il m'arrive très fréquemment, d'envoyer des bouts de codes à des internautes en détresse, des clients ayant identifié un besoin qui me prend 5 min à régler, ou tout simplement sur mon blog.
Aujourd'hui encore, beaucoup (trop ??) de personnes me demandent de traduire mon code, car il n'arrive à le comprendre. Non pas que le code que je fournis soit trop compliqué, mais tout simplement parce qu'il tire pleinement partie des fonctionnalités de C# 3.0 et du .net 3.5 de manière générale.
Au départ, cela ne me posait aucun souci, mais avec le temps, je dois avouer que c'est de plus en plus contraignant, surtout lié au nombre de lignes supplémentaires à écrire en .net 2.0 et à la complexité que cela peut parfois rajouter, notamment lorsque l'on fait un usage intensif des divers Linq Providers.
L'objectif de ce post, est donc de vous proposer un rappel des nouveautés apportées par C# 3.0 à l'époque, et de commencer à migrer en douceur vers un modèle de développement orienté C# 4.0
Commencons donc sans plus tarder notre rappel C# 3.0 :
Les types implicites avec le mot clé var
Le mot clé var permet au développeur de laisser le soin au compilateur de déduire le type d'une variable, il évite ainsi au développeur, dans des situations « complexes » (notamment avec Linq) de se casser la tête à résoudre les types ou des situations avec un type de longueur kilométrique (merci les génériquesJ). Un simple mot clé var, combiné à l'utilisation de l'intellisense nous simplifie grandement la vie !
1: //au lieu d'écrire... (C# 2.0)
2: using (SPSite siteColl = new SPSite("http://ws2008dc01:10000")) { 3: using (SPWeb currentWeb = siteColl.OpenWeb()) { 4: foreach (SPList list in currentWeb.Lists) { 5: if (!list.Hidden) Console.WriteLine(list.Title);
6: }
7: }
8: }
9:
10: //...écrivez plutot (C# 3.0)
11: using (var siteColl = new SPSite("http://ws2008dc01:10000")) { 12: using (var currentWeb = siteColl.OpenWeb()) { 13: foreach (SPList list in currentWeb.Lists) { 14: if (!list.Hidden) Console.WriteLine(list.Title);
15: }
16: }
17: }
Les initialisateurs d'objets
Les initialisateurs d'objets permettent d'initialiser les propriétés publiques d'une classe, sans forcément passer par un constructeur, entrainant la plupart du temps un gain de temps considérable.
1: //au lieu d'écrire... (C# 2.0)
2: using (SPSite siteColl = new SPSite("http://ws2008dc01:10000")) { 3: siteColl.AllowUnsafeUpdates = true;
4: siteColl.CatchAccessDeniedException = true;
5: siteColl.PortalName = "My Portal";
6: siteColl.PortalUrl = "http://portal";
7:
8: using (SPWeb currentWeb = siteColl.OpenWeb()) { } 9: }
10:
11: //...écrivez plutot (C# 3.0)
12: using (var siteColl = new SPSite("http://ws2008dc01:10000") { 13: AllowUnsafeUpdates = true, CatchAccessDeniedException = true,
14: PortalName = "My Portal", PortalUrl = "http://portal"
15: }) { 16: using (SPWeb currentWeb = siteColl.OpenWeb()) { } 17: }
Les méthodes d'extension
Les méthodes d'extension nous permettent d'étendre une classe existente en y rajoutant des méthodes à la volée.
1: //au lieu d'écrire... (C# 2.0 + beaucoup de farniente)
2: foreach (SPListItem item in cList.Items) { 3: string title = item["Title"]==null?"":item["Title"].ToString();
4: string name= item["Name"]==null?"": item["Name"].ToString();
5:
6: XmlSerializer serializer = new XmlSerializer(typeof(Employee));
7: string data = (item["Employee"]==null)? "": item["Employee"].ToString();
8: if (data=="")throw new Exception("La colonne employee ne contient pas d'informations sérialisées."); 9: MemoryStream stream = new MemoryStream(Encoding.Default.GetBytes(data));
10: var employeeData = (Employee)serializer.Deserialize(stream);
11: }
12:
13:
14: //....écrivez plutot (C# 3.0)
15: foreach (SPListItem item in cList.Items) { 16: var title = item.IfNullReturnEmpty("Title"); 17: var name = item.IfNullReturnEmpty("Name"); 18: var employeeData = item.DeserializeAsEmployee("Employee"); 19: }
20: //Avec en plus nos methodes d'extension
21: public static class Extensions { 22:
23: public static string IfNullReturnEmpty(this SPListItem item, string Column) { 24: return item[Column] == null ? "" : item[Column].ToString();
25: }
26:
27: public static Employee DeserializeAsEmployee(this SPListItem item, string Column) { 28: var serializer = new XmlSerializer(typeof(Employee));
29: var data = item.IfNullReturnEmpty(Column);
30: if (data == "") throw new Exception("La colonne employee ne contient pas d'informations sérialisées."); 31: var stream = new MemoryStream(Encoding.Default.GetBytes(data));
32: return (Employee)serializer.Deserialize(stream);
33: }
34: }
Le mot clé this dans la signature de la méthode d'extension permet de déterminer le type auquel sera rattachée la méthode (ici les méthodes sont rattachées aux classes SPListItem).
Les types anonymes
A l'instar des méthodes anonymes, les types anonymes vont être intéressants lorsque l'on souhaite implémenter rapidement et localement un type.
1: //au lieu d'écrire... (C# 2.0)
2: public class Contact { 3: string m_firstName;
4: public string FistName { 5: get { return this.m_firstName; } 6: set { this.m_firstName = value; } 7: }
8:
9: string m_lastName;
10: public string LastName { 11: get { return this.m_lastName; } 12: set { this.m_lastName = value; } 13: }
14:
15: string m_company;
16: public string Company { 17: get { return this.m_company; } 18: set { this.m_company = value; } 19: }
20: }
21:
22: //puis
23: Contact appContact1 = new Contact();
24: appContact1.FistName = item["FirstName"].ToString();
25: appContact1.LastName = item["LastName"].ToString();
26: appContact1.Company = item["Company"].ToString();
27: string msg;
28: msg = string.Format("Contact {0} {1} of {2} has been added !", appContact1.FistName, 29: appContact1.LastName, appContact1.Company);
30:
31:
32: //...écrivez plutot (C# 3.0)
33: var appContact2 = new { 34: FirstName = item["FirstName"].ToString(), LastName = item["LastName"].ToString(),
35: Company = item["Company"].ToString()
36: };
37: msg = string.Format("Contact {0} {1} of {2} has been added !", appContact2.FistName, 38: appContact2.LastName, appContact2.Company);
Les expressions Lambda
Les expressions Lambda sont des fonctions anonymes.
1: //au lieu d'écrire... (C# 2.0)
2: SPSecurity.RunWithElevatedPrivileges(delegate() { 3: cItem["Created"] = DateTime.Now;
4: cItem.SystemUpdate();
5: });
6:
7: //...écrivez plutot (C# 3.0)
8: SPSecurity.RunWithElevatedPrivileges(() => { 9: cItem["Created"] = DateTime.Now;
10: cItem.SystemUpdate();
11: });
L'opérateur Lambda '=>' se lit 'conduit à'
Les propriétés automatiques
Les propriétés automiques vont partie des apports les plus appréciables. Plus besoin d'implémenter les champs de stockage pour vos propriétés, le compilateur sais désormais les gérer automatiquement !
Précisez simplement dans votre code l'accessibilité de votre propriété (get et/ou set), et le compilateur se chage du reste. Ainsi nous pouvons réécrire la classe Contact précédemment définie comme ceci :
1: public class Contact2 { 2: public string FirstName { get; set; } 3: public string LastName { get; set; } 4: public string Company { get; set; } 5: }
3 lignes !
Vraiment appréciable.
Les méthodes partielles
Un des mécanismes que j'utilise le moins.
Vous pouvez donc désormais utiliser le mot clé partial sur vos méthodes pour séparer la déclaration de votre méthode de l'implémentation dans plusieurs fichiers de code.
Linq
Une véritable révolution !
Linq est un modèle de requêtage de données qui permet d'unifier l'accès aux données.
Que vous souhaitiez récupérer des données stockées dans vos objets métiers ou dans votre base de données ou un fichier texte, ou, etc…
Vous pouvez utiliser Linq de manière totalement transparente et homogène ; ce dernier fait abstraction de la source de données sous-jacente.
1: //au lieu d'écrire... (C# 2.0)
2: List<SPListItem> specialItems = new List<SPListItem>();
3: foreach (SPListItem item in list.Items) { 4: if (item["Title"].ToString().StartsWith("special_")) 5: specialItems.Add(item);
6: }
7:
8:
9: //...écrivez plutot (C# 3.0)
10: var specialItem = from SPListItem item in list.Items
11: where item["Title"].ToString().StartsWith("special_") 12: select item;
voila, vous êtes désormais paré à écrire du code C# 3.0 dans vos développements SharePoint !