Jan 15

Kunal Chowdhury a publié sur son blog un graphique représentant en un coup d’œil les évolutions du langage C#.
Il y détaille également ces évolutions.

Il peut être intéressant d’avoir ce graphe sous la main !
Evolution of C# (1.0 - 6.0) - www.kunal-chowdhury.com

Source : http://www.kunal-chowdhury.com/2016/01/csharp-basics.html

Jan 12

Logo Visual Studio 2012Maintenant qu’une grosse partie du code des projets autour du Framework .Net est disponible, il peut être intéressant de pouvoir le consulter facilement pendant que l’on développe. Aujourd’hui, utiliser le raccourci F12 (« Go To Definition ») sur une méthode du Framework affiche uniquement les métadatas de la classe et de la méthode (notamment sa signature).

Le plugin Ref12 permet de remplacer cela par l’ouverture d’une page web pointant sur le site de Microsoft regroupant les sources du Framework et qui affiche les sources de la méthode et de la classe correspondante.

 

Fév 18

Logo Visual StudioDans un précédent article, nous avons abordé la question de la transformation du fichier App.Config, en fonction de l’environnement cible.
Or généralement, la cible par défaut, Debug est uniquement utilisée pour le développement et utilise donc une configuration particulière qui ne doit pas forcément être publiée.

Ainsi, sur tous mes projets, je créé les cibles Recette, Qualif, Production (et autres, en fonction du besoin), tout en conservant les cibles existantes Debug et Release. La première étant la configuration utilisée pour le développement, la seconde étant rarement utilisée.
Le problème est donc qu’il arrive occasionnellement de lancer une publication sans avoir changé l’environnement cible, ce qui provoque la copie de paramètres de configuration de débogage sur un environnement ne correspondant pas à cette configuration.

Afin d’éviter de publier accidentellement en configuration Debug, il suffit d’ajouter les lignes suivantes à la fin du fichier *.csproj de votre projet principal (à ouvrir avec un éditeur texte), juste avant la balise de clôture </project> :

<Target Name="BeforePublish">
	<Error Condition="'$(Configuration)'=='Debug'" Text="Ce projet ne doit pas être publié en DEBUG. Choisissez l'environnement cible approprié." />
	<Error Condition="'$(Configuration)'=='Release'" Text="Ce projet ne doit pas être publié en RELEASE. Choisissez l'environnement cible approprié." />
</Target>

Cette modification va interrompre la publication si la configuration actuellement sélectionnée est Debug ou Release (car je ne l’utilise pas) en affichant le message spécifié.

Jan 22

Logo Visual StudioEric Lippert, développeur ayant participé au design du langage C# chez Microsoft et ayant participé au développement du compilateur publie actuellement sur son blog, Fabulous Adventures In Coding, une série de billets extrêmement intéressants concernant les décisions prises et les nombreuses optimisations mises en place lors de l’introduction de la classe Nullable<> pour la version 2.0 du Framework .NET.

Ils sont notamment intéressants car ils permettent d’avoir une toute petite idée du travail titanesque qu’est la création d’un langage et d’un compilateur, des choix qu’il est nécessaire de faire, de tous les facteurs qu’il faut garder en tête lorsque l’on décide de la moindre modification, surtout quand on considère qu’il s’agit là uniquement de l’ajout d’une seule classe (certes très utile). Il est également impressionnant de voir la quantité de techniques utilisées pour optimiser la compilation du code.

Attention, ces billets sont très techniques (et en anglais) !

Je mettrais à jour l’article lorsqu’Eric ajoutera d’autres chapitres.

Fév 08

Il arrive régulièrement de devoir écrire une méthode générique qui accepte n’importe quel type Enum comme paramètre.
Voici un exemple de cas où cela peut s’avérer nécessaire.

Il s’agit rendre générique une méthode LogError, dont le second paramètre est un type Enum, qui permet de spécifier la catégorie :

public enum LogCategory
{
	Default,
	UserInterface,
	BusinessLogic,
	DataAccess,
	Security,
	Errors
}

Cette classe LogCategory est définie dans une librairie de classes (par exemple DataAccess). On a également une application web (par exemple Web1) qui appelle cette méthode LogError pour la loguer mais le problème c’est que cette application web a elle-même défini sa propre classe LogCategory.
Donc lorsque l’énumération LogCategory de Web1 est passée en paramètre de la méthode LogError, cela génère une erreur de compilation Cannot convert Web1.LogCategory into DataAccess.LogCategory car il s’agit bien entendu de deux classes différentes dans deux projets différents.

Il est donc nécessaire de créer une méthode LogError générique qui accepterait n’importe quel énumération comme paramètre.

Voici une première version de cette méthode :

public static void LogError<T>(string msg, T logCat)
{
	//Here T is generic type.
	EntLib.Logger.Write(msg, logCat.ToString(), 3, 1000, TraceEventType.Error);
	//EntLib = Microsoft.Practices.EnterpriseLibrary.Logging;
}

Mais cette méthode est devenue trop générique car T peut être de n’importe quel type. Il est donc nécessaire d’ajouter une contrainte sur le type de T afin de le limiter à des énumérations, grâce à l’utilisation de la clause where.

public static void Error<T>(string msg, T logCat) where T: Enum
{
	//Here T is generic type.
	EntLib.Logger.Write(msg, logCat.ToString(), 3, 1000, TraceEventType.Error);
	//EntLib = Microsoft.Practices.EnterpriseLibrary.Logging;
}

Mais cela ne fonctionne pas, car cela génère une erreur de compilation Type Expected. Apparemment il n’y a pas de manière simple de spécifier une contrainte sur une énumération. Étant donné que le type Enum implémente l’interface IConvertible, une solution de contournement pourrait être de créer une contrainte sur cette interface :

public static void Error<T>(string msg, T logCat) where T: struct, IConvertible
{
	//Here T is generic type.
	EntLib.Logger.Write(msg, logCat.ToString(), 3, 1000, TraceEventType.Error);
	//EntLib = Microsoft.Practices.EnterpriseLibrary.Logging;
}

Cela limite un peu le type de paramètre, l’instruction LogError<SomeXClass>("message", objOfSomeXClass) génère une erreur de compilation :

The type ‘SomeXClass’ must be a non-nullable value type in order to use it as parameter ‘T’ in the generic type or method ‘LogError<T>(string, T)’

C’est mieux , il est toujours possible de passer un objet d’un type implémentant l’interface IConvertible mais c’est plutôt rare.
Il est également possible de vérifier dans le code le type de T afin de valider qu’il est bien de type Enum et restreindre encore plus.

Version finale :

public static void Error<T>(string msg, T logCat)  where T : struct, IConvertible
{
	if (!typeof(T).IsEnum)
	{
		string errorMessage = string.Format("{0} must be an enumerated type", typeof(T).ToString());
		throw new ArgumentException(errorMessage, typeof(T).ToString());
	}
	EntLib.Logger.Write(msg, logCat.ToString(), 3, 1000, TraceEventType.Error);
	//EntLib = Microsoft.Practices.EnterpriseLibrary.Logging;
}

Source : Shailesh sur Broken Code.