10janv. 2012

CSharp 4.0 : Le piège de l'UnaryExpression

Tout a commencé dans la méthode qui me sert à récupérer le nom d'une propriété. Je passe ma propriété en paramètre d'une fonction en tant que lambda expression. A l'exécution, j'obtenais une NullReferenceException.

So null

Voici le code source à l'origine de l'exception:

string propertyName 
    = (property.Body as MemberExpression)
        .Member.Name

A l'inspecteur, property n'était pas null - et property.Body non plus. Sachant que j'utilise cette méthode pour récupérer le nom de mes propriétés partout, depuis des semaines, le comportement est étrange.

La variable property est un paramètre déclaré de la façon suivante:

Expression<Func<object>> property

Un peu de débogage montre que, lors des autres appels, les objets contenus dans property sont tels que property.Body est une instance de MemberExpression. Ce qui explique qu'il n'y ait aucun problème. Celle qui fait planter le système est du type UnaryExpression.

Mission cast-impossible

En tentant un cast dans l'inspecteur de Visual Studio, j'obtiens une InvalidCastException.

Un peu de recherche sur Internet m'apprends que l'inferrence de type la coupable.

Lorsqu'un boxing intervient, l'objet récupéré est de type UnaryExpression. Cela explique l'erreur de cast.

Heureusement, il est toujours possible de récupérer le MemberExpression sous-jacent:

MemberExpression expression 
    = ((UnaryExpression)property.Body).Operand 
        as MemberExpression;

Ce patch fonctionne, mais c'est du QuickNDirty. La solution ultime est d'utiliser la généricité au niveau de la déclaration de l'expression property:

La solution

Typer l'expression:

 Expression<Func<TPropertyWatch>> property 

De cette manière aucune inférence de type n'est effectuée - et property.Body sera toujours un MemberExpression. La modification peut-être impactante au niveau d'une application, mais sur le long terme, le développeur est gagnant.

Sources

aucun commentaire

Fil des commentaires de ce billet

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.