Archives par étiquette : C#

image

Nothing est différent de null

Une des différences les plus importantes entre le VB et le C# est la gestion de la nullité des types.

En VB, on utilise le mot clé Nothing et contrairement à ce que beaucoup de développeurs VB pensent,

le mot clé Nothing n’a (presque) rien à voir avec le null tel que l’on peut le connaitre dans la plupart des langages.

En effet, en VB le Nothing équivaut à Default.

La différence est très importante notamment pour les types valeurs, puisqu’il est tout à fait possible d’assigner Nothing à un type valeur ! Le type prend alors sa valeur par défaut, comme 0 pour les types numériques, ou Date.DateMin pour les dates :

image

 

Bien évidemment, pour les types références, la valeur affectée sera l’équivalent d’un null puisqu’aucune instance n’est créé lors de l’affectation de Nothing.

Pour rappel si l’on essaie de faire “la même chose” en C#, on se retrouve très justement avec une erreur de compilation :

image

Dans le prochain post, nous verrons l’impact de cette différence sur les tests d’égalité à Nothing.

La co-évolution doit aussi être valable pour les outils

Ce
fut une des annonces de la PDC08 afin de palier aux différents décalages fonctionnels
des langages C# et VB, l’équipe Langages de Microsoft a indiqué que les deux langages
allaient à présent suivre la même évolution.

Cela signifie que toutes les nouvelles fonctionnalités qui seront implémentées dans
un des deux langages sera également ajouté dans l’autre. De plus, les fonctionnalités
existantes importantes qui manqueraient à l’un ou l’autre des langages sont en train
d’être comblés (ex : support des arguments optionnels et nommés en C# 4 ou encore
les itérateurs dans VB vNext).

Vous pouvez trouver l’explication de cette décision dans cette interview du regretté
Lucas Bolognese effectuée par Ted Neward :

Vous pouvez également lire la version
écrite via ce post de Scott Wiltamuth
.

Ce changement de direction ravit une grande majorité des développeurs C# et VB. Il
reste cependant un pas très important à franchir :

la co-evolution au niveau des outils !!!

Le dernier exemple qui démontre ce besoin date d’aujourd’hui
avec la
mise à disposition en version finale (RTW) des outils pour développer sous Windows
Phone 7 pour les développeurs VB
soit plus d’un mois (si je me limite à l’update
d’Octobre et donc sans compter la version initiale) après la mise à disposition du
kit de développement équivalent pour les développeurs C# !

De plus cette version n’est en réalité pas équivalente à la version C# puisque que
la version express de Visual Studio (gratuite) n’est pas supportée !

Alors, oui, fournir une compatibilité pour les développeurs VB est plus complexe que
pour les développeurs C# du fait des spéficités du langage et de sa library associée
Microsoft.VisualBasic.dll, mais bon… Cette complexité peut être anticipée et Microsoft
pourrait très bien dimensionner l’équipe responsable de cette implémentation en conséquence.

Il est bien beau de fournir des capacités semblables au niveau des langages encore
faut-t-il proposer aux deux communautés de développeurs de pouvoir développer les
mêmes types d’applications (au même moment) !

image

Les concaténations de chaines en C#

image

Je viens de publier un nouvel article sur TechHeadBrothers sur les différents types
de concaténations en C#, leur implémentation en interne, les optimisations effectuées
par le compilateur ainsi qu’un bench des différentes méthodes afin de savoir quand
utiliser tel ou telle méthode.

Vous pouvez le consulter ici :

Article
sur THB

image

Aller plus loin avec les Threads

Lorsque l’on parle de Thread avec le framework .net, le reflexe naturel est de penser
au namespace System.Threading. Ce namespace contient en effet presque tout ce que
.net vous propose afin de gérer le multithreading.

Cela est peu connu et peu utilisé, mais il est possible de dépasser certaines limites
de la classe Thread en utilisant une classe auxiliaire ProcessThread présente quand
à elle dans System.Diagnostics. Cette classe fournit tout un tas de service interessant
comme la possibilité de définir l’affinité d’un thread afin de le faire exécuter sur
un processeur en particulier ce qui n’est pas possible à l’aide de la traditionnelle
classe Thread :

using System.Diagnostics;

namespace FurtherWithThreads
{
    class Program
    {
        static void Main(string[] args)
        {
            int threadId = AppDomain.GetCurrentThreadId();
            SetProcessorAffinity(threadId,1);
            while(true)
            {
                
            }
        }

        static void SetProcessorAffinity(int threadId, int processor)
        {
            var processorThread = (from ProcessThread t in Process.GetCurrentProcess().Threads
                                  where t.Id == threadId
                                  select t).Single();
            processorThread.ProcessorAffinity = (IntPtr) processor;
        }
    }
}

image image

Comme vous pouvez le constater le code s’exécute bien sur des cœurs différents comme
souhaité.

image

Mot-clé sizeof et mode unsafe

En C# si l’on souhaite utiliser le mot clé sizeof, la documentation précise qu’il
est nécessaire d’utiliser le mode unsafe
grâce au mot-clé du même nom.

En effet, si l’on souhaite par exemple récupérer la taille d’une struct à l’aide de
ce mot-clé et non via l’utilisation de la classe Marshal il vous faudra écrire :

public struct MyStruct
{
    public int A;
    public int B;
}

class Program
{
    unsafe static void Main(string[] args)
    {
        int s = sizeof (MyStruct);
        Console.WriteLine(s.ToString());
    }
}

Mais bizarrement, si vous souhaitez faire un sizeof du type int, vous n’aurez pas
besoin d’utiliser de code unsafe et R# indique
même que le mot-clé unsafe devrait être supprimé car redondant :

image

Mais comment ce contexte peut-il être redondant puisque nous n’avons utilisé le mot
clé unsafe qu’une seule fois, et qu’il ne l’était pas dans l’exemple précédent ? La
réponse est simple mais si elle n’est pas évidente au premier abord : il n’est plus
nécessaire depuis C# 2 de spécifier un contexte unsafe lors de l’utilisation de l’opérateur
sizeof sur les types .net prédéfinis.

On peut d’ailleurs voir la différence de comportement du compilateur dans les deux
cas évoqués puisque lors de l’utilisation de l’opérateur sizeof sur le type int, le
compilo inline directement le résultat :

private static void Main(string[] args)
{
    Console.WriteLine(4.ToString());
}

Tandis que lors de l’utilisation avec un type personnalisé, la valeur ne sera pas
inlinée, et le code généré fera appel à l’instruction sizeof présente dans l’Intermediate
Language :

private static void Main(string[] args)
{
    Console.WriteLine(sizeof(MyStruct).ToString());
}

Pour plus d’infos :

http://blogs.msdn.com/abhinaba/archive/2006/02/24/538525.aspx

03fig01

Je HAIS les regions

Les regions sont incontestablement la fonctionnalité que je déteste et qui m’insupporte
le plus dans Visual Studio. En voir dans du code, me fait enrager, grogner, avoir
des boutons dans 98% des cas où je les rencontre.

Les regions permettent de définir différentes zones dans du code, zones qui peuvent
être nommées et qui peuvent être rétractables. Le principal reproche que je trouve
aux régions réside tout simplement dans le rôle même de cette fonction : MASQUER
LE CODE
.

Car après tout, les régions ont été créés dans un seul et unique but : masquer
du code
que le développeur ne doit pas voir ou modifier :

Cela avait donc une utilité avant que les classes partielles existent afin de masquer
du code
qui est généré et qui donc par définition ne doit pas être modifié
(sous peine de voir les modifications supprimées lors de la prochaine génération de
code) en le plaçant dans un autre fichier.

Vous l’avez compris, je ne comprends pas quel est l’intérêt de masquer du code. Lorsque
je consulte des fichiers sources je souhaite avoir la meilleure lisibilité possible
afin de comprendre le fonctionnement du code que je suis en train de lire. Le voir
masqué m’oblige à utiliser mes dons de contorsionniste des doigts afin de déplier
ces fameuses régions qui, pour certains développeurs, servent à “ranger” ou “classer”
du code source de “manière plus propre”.  Dans la très majorité des cas, si vous
avez besoin de “ranger” votre code source présent dans une classe en plus zone, c’est
que votre classe fait beaucoup trop de choses que ce qu’elle devrait faire. Repenser
la séparation des responsabilités permet de résoudre le problème. Si vous regroupez
plusieurs méthodes et/ou propriétés dans une région particulière, il y a une forte
probabilité que cet ensemble devrait se trouver dans une autre classe. Et si vous
groupez des lignes de code d’une même méthode en plusieurs régions, cela signifie
que votre méthode à trop de responsabilité et qu’il serait bon de la splitter en différentes
méthodes distinctes.

Le seul avantage que je vois donc aux régions, et qu’il permet de voir du premier
coup d’œil quel est le code qu’il est urgent de factoriser.