Remarque: Cette question a été posée avant l'introduction de l' .?
opérateur dans C # 6 / Visual Studio 2015 .
Nous avons tous été là, nous avons une propriété profonde comme cake.frosting.berries.loader dont nous devons vérifier si elle est nulle, donc il n'y a pas d'exception. La façon de faire est d'utiliser une instruction if de court-circuit
if (cake != null && cake.frosting != null && cake.frosting.berries != null) ...
Ce n'est pas vraiment élégant, et il devrait peut-être y avoir un moyen plus simple de vérifier toute la chaîne et de voir si elle se heurte à une variable / propriété nulle.
Est-il possible d'utiliser une méthode d'extension ou serait-ce une fonctionnalité de langage, ou est-ce juste une mauvaise idée?
Réponses:
Nous avons envisagé d'ajouter une nouvelle opération "?". à la langue qui a la sémantique souhaitée. (Et il a été ajouté maintenant; voir ci-dessous.) Autrement dit, diriez-vous
et le compilateur générerait toutes les vérifications de court-circuit pour vous.
Cela n'a pas fait la barre pour C # 4. Peut-être pour une future version hypothétique du langage.
Mise à jour (2014): l'
?.
opérateur est désormais prévu pour la prochaine version du compilateur Roslyn. Notez qu'il y a encore un débat sur l'analyse syntaxique et sémantique exacte de l'opérateur.Mise à jour (juillet 2015): Visual Studio 2015 a été publié et est livré avec un compilateur C # qui prend en charge les opérateurs conditionnels null
?.
et?[]
.la source
Je me suis inspiré de cette question pour essayer de découvrir comment ce type de vérification profonde des null peut être effectué avec une syntaxe plus facile / plus jolie en utilisant des arbres d'expression. Bien que je sois d'accord avec les réponses indiquant que cela pourrait être une mauvaise conception si vous avez souvent besoin d'accéder à des instances au plus profond de la hiérarchie, je pense également que dans certains cas, comme la présentation des données, cela peut être très utile.
J'ai donc créé une méthode d'extension, qui vous permettra d'écrire:
Cela renverra les baies si aucune partie de l'expression n'est nulle. Si nul est rencontré, nul est renvoyé. Il y a cependant quelques mises en garde, dans la version actuelle, il ne fonctionnera qu'avec un accès membre simple, et il ne fonctionne que sur .NET Framework 4, car il utilise la méthode MemberExpression.Update, qui est nouvelle dans la v4. Voici le code de la méthode d'extension IfNotNull:
Cela fonctionne en examinant l'arborescence des expressions représentant votre expression et en évaluant les parties l'une après l'autre; à chaque fois en vérifiant que le résultat n'est pas nul.
Je suis sûr que cela pourrait être étendu afin que d'autres expressions que MemberExpression soient prises en charge. Considérez cela comme du code de preuve de concept, et gardez à l'esprit qu'il y aura une pénalité de performance en l'utilisant (ce qui n'aura probablement pas d'importance dans de nombreux cas, mais ne l'utilisez pas dans une boucle serrée :-))
la source
DynamicInvoke
là-bas. J'évite religieusement ça :)J'ai trouvé cette extension très utile pour les scénarios d'imbrication profonde.
C'est une idée que j'ai dérivée de l'opérateur de fusion nul en C # et T-SQL. La bonne chose est que le type de retour est toujours le type de retour de la propriété interne.
De cette façon, vous pouvez faire ceci:
... ou une légère variation de ce qui précède:
Ce n'est pas la meilleure syntaxe que je connaisse, mais cela fonctionne.
la source
En plus de violer la loi de Déméter, comme Mehrdad Afshari l'a déjà souligné, il me semble que vous avez besoin d'une "vérification profonde des nullités" pour la logique de décision.
C'est le plus souvent le cas lorsque vous souhaitez remplacer des objets vides par des valeurs par défaut. Dans ce cas, vous devez envisager d'implémenter le modèle d'objet nul . Il agit comme un substitut pour un objet réel, fournissant des valeurs par défaut et des méthodes «sans action».
la source
Mise à jour: à partir de Visual Studio 2015, le compilateur C # (version 6 du langage) reconnaît désormais l'
?.
opérateur, ce qui simplifie la «vérification approfondie des null». Voir cette réponse pour plus de détails.En plus de reconcevoir votre code, comme le suggère cette réponse supprimée , une autre option (bien que terrible) serait d'utiliser un
try…catch
bloc pour voir si uneNullReferenceException
erreur se produit à un moment donné pendant cette recherche approfondie de propriété.Personnellement, je ne ferais pas cela pour les raisons suivantes:
NullReferenceException
s ne devrait probablement jamais être pris explicitement. (Voir cette question .)Cela devrait presque certainement être une fonctionnalité de langage (qui est disponible en C # 6 sous la forme des opérateurs
.?
et?[]
), à moins que C # n'ait déjà une évaluation paresseuse plus sophistiquée, ou à moins que vous ne souhaitiez utiliser la réflexion (qui n'est probablement pas non plus une bonne idée pour des raisons de performances et de sécurité de type).Puisqu'il n'y a aucun moyen de passer simplement
cake.frosting.berries.loader
à une fonction (elle serait évaluée et lèverait une exception de référence nulle), vous devriez implémenter une méthode de recherche générale de la manière suivante: Il prend un objets et les noms de propriétés à Chercher:(Remarque: code modifié.)
Vous voyez rapidement plusieurs problèmes avec une telle approche. Premièrement, vous n'obtenez aucune sécurité de type et possibilité d'encadrer les valeurs de propriété d'un type simple. Deuxièmement, vous pouvez soit revenir
null
si quelque chose ne va pas, et vous devrez vérifier cela dans votre fonction d'appel, ou vous lever une exception, et vous êtes de retour à votre point de départ. Troisièmement, cela pourrait être lent. Quatrièmement, cela a l'air plus laid que ce avec quoi vous avez commencé.Je resterais soit avec:
ou allez avec la réponse ci-dessus par Mehrdad Afshari.
PS: Quand j'ai écrit cette réponse, je n'ai évidemment pas considéré les arbres d'expression pour les fonctions lambda; voir par exemple la réponse de @driis pour une solution dans ce sens. Il est également basé sur une sorte de réflexion et peut donc ne pas fonctionner aussi bien qu'une solution plus simple (
if (… != null & … != null) …
), mais il peut être jugé plus agréable d'un point de vue syntaxique.la source
Bien que la réponse de Driis soit intéressante, je pense que c'est un peu trop cher en termes de performances. Plutôt que de compiler de nombreux délégués, je préférerais compiler un lambda par chemin de propriété, le mettre en cache, puis le réinvoquer de nombreux types.
NullCoalesce ci-dessous fait exactement cela, il renvoie une nouvelle expression lambda avec des vérifications nulles et un retour par défaut (TResult) au cas où un chemin serait nul.
Exemple:
Renverra une expression
Code:
la source
Une option est d'utiliser le Null Object Patten, donc au lieu d'avoir null quand vous n'avez pas de gâteau, vous avez un NullCake qui renvoie un NullFosting etc. Désolé, je ne suis pas très doué pour expliquer cela mais d'autres personnes le sont, voir
la source
Moi aussi, j'ai souvent souhaité une syntaxe plus simple! Il devient particulièrement laid quand vous avez méthode de retour des valeurs qui pourraient être nulle, car alors vous avez besoin des variables supplémentaires (par exemple:
cake.frosting.flavors.FirstOrDefault().loader
)Cependant, voici une alternative assez décente que j'utilise: créer une méthode d'assistance Null-Safe-Chain. Je me rends compte que c'est assez similaire à la réponse de @ John ci-dessus (avec la
Coal
méthode d'extension) mais je trouve que c'est plus simple et moins tapant. Voici à quoi cela ressemble:Voici l'implémentation:
J'ai également créé plusieurs surcharges (avec 2 à 6 paramètres), ainsi que des surcharges qui permettent à la chaîne de se terminer par un type valeur ou par défaut. Cela fonctionne vraiment bien pour moi!
la source
Il existe un projet Maybe codeplex qui implémente Maybe ou IfNotNull en utilisant des lambdas pour les expressions profondes en C #
Exemple d'utilisation:
Le lien a été suggéré dans une question similaire Comment vérifier les valeurs nulles dans une expression lambda profonde?
la source
Comme le suggère John Leidegren de réponse , une approche de travail autour est d'utiliser des méthodes d'extension et les délégués. Leur utilisation pourrait ressembler à ceci:
L'implémentation est compliquée car vous devez la faire fonctionner pour les types valeur, les types référence et les types valeur Nullable. Vous pouvez trouver une implémentation complète dans la réponse de Timwi à Quelle est la bonne façon de vérifier les valeurs nulles? .
la source
Ou vous pouvez utiliser la réflexion :)
Fonction de réflexion:
Usage:
My Case (retourne DBNull.Value au lieu de null dans la fonction de réflexion):
la source
Essayez ce code:
la source
J'ai posté ceci hier soir, puis un ami m'a signalé cette question. J'espère que ça aide. Vous pouvez alors faire quelque chose comme ceci:
Lisez le blog complet ici .
Le même ami a également suggéré que vous regardiez ceci .
la source
Expression
si vous allez juste compiler et attraper? Utilisez simplement un fichierFunc<T>
.J'ai légèrement modifié le code à partir d' ici pour le faire fonctionner pour la question posée:
Et oui, ce n'est probablement pas la solution optimale en raison des implications de performance try / catch, mais cela fonctionne:>
Usage:
la source
Là où vous devez y parvenir, procédez comme suit:
Usage
ou
Implémentation de classe d'assistance
la source
J'aime l'approche d'Objective-C:
"Le langage Objective-C adopte une autre approche à ce problème et n'appelle pas de méthodes sur nil mais renvoie à la place nil pour toutes ces invocations."
la source