L'opérateur de coalescence nulle en c # vous permet de raccourcir le code
if (_mywidget == null)
return new Widget();
else
return _mywidget;
Jusqu'à:
return _mywidget ?? new Widget();
Je continue de trouver qu'un opérateur utile que j'aimerais avoir en C # serait celui qui vous permettrait de renvoyer une propriété d'un objet, ou une autre valeur si l'objet est nul. Je voudrais donc remplacer
if (_mywidget == null)
return 5;
else
return _mywidget.Length;
Avec:
return _mywidget.Length ??! 5;
Je ne peux m'empêcher de penser qu'il doit y avoir une raison pour que cet opérateur n'existe pas. Est-ce une odeur de code? Y a-t-il une meilleure façon d'écrire cela? (Je connais le modèle d'objet nul mais il semble exagéré de l'utiliser pour remplacer ces quatre lignes de code.)
c#
code-smell
null
Ben Fulton
la source
la source
??!
est un opérateur en C ++. :-)Réponses:
Je veux vraiment une fonctionnalité de langage C # qui me permette de faire en toute sécurité x.Prop.SomeOtherProp.ThirdProp sans avoir à vérifier chacun de ceux-ci pour null. Dans une base de code où j'ai dû faire beaucoup ce genre de "traversées de propriétés profondes", j'ai écrit une méthode d'extension appelée Navigate qui a avalé NullReferenceExceptions et a renvoyé à la place une valeur par défaut. Je pourrais donc faire quelque chose comme ça:
L'inconvénient est qu'il a une odeur de code différente: les exceptions avalées. Si vous vouliez faire quelque chose comme ceci "à droite", vous pourriez prendre la lamdba comme expression et modifier l'expression à la volée pour ajouter les vérifications nulles autour de chaque accesseur de propriété. Je suis allé pour "rapide et sale" et ne l'ai pas implémenté de cette façon "meilleure". Mais peut-être que lorsque j'aurai quelques cycles de réflexion de rechange, je reverrai cela et le posterai quelque part.
Pour répondre plus directement à votre question, je suppose que la raison pour laquelle il ne s'agit pas d'une fonctionnalité est que le coût de mise en œuvre de la fonctionnalité dépasse les avantages de la fonctionnalité. L'équipe C # doit choisir les fonctionnalités sur lesquelles se concentrer, et celle-ci n'a pas encore atteint le sommet. Juste une supposition même si je n'ai pas d'informations privilégiées.
la source
Je pense que vous pourrez le faire avec C # 6 tout simplement maintenant:
Notez l'opérateur à condition nulle
?.
sur le côté gauche._mywidget?.Length
renvoie null si_mywidget
est nul.Un simple opérateur ternaire pourrait être plus facile à lire, comme d'autres l'ont suggéré.
la source
Ce n'est vraiment qu'une spéculation sur la raison pour laquelle ils ne l'ont pas fait. Après tout, je ne crois pas ?? était dans la première version C #.
Quoi qu'il en soit, je voudrais simplement utiliser l'opérateur conditionnel et l'appeler un jour:
Le ?? est juste un raccourci vers l'opérateur conditionnel.
la source
5
comme réponse au cas où il ne serait pas là. Vous devez examiner votre conception avant de commencer à demander des opérateurs spéciaux.Il ressemble à l'opérateur ternaire:
la source
Personnellement, je pense que c'est dû à la lisibilité. Dans le premier exemple, le se
??
traduit assez bien par "Êtes-vous là ?? Non, faisons cela".Dans le deuxième exemple,
??!
est clairement WTF et ne signifie rien pour le programmeur .... l'objet n'existe pas, donc je ne peux pas accéder à la propriété donc je vais en retourner 5. Qu'est-ce que cela signifie même? Qu'est-ce que 5? Comment arrivons-nous à la conclusion que 5 est une bonne valeur?Bref, le premier exemple a du sens ... pas là, c'est nouveau . Dans le second, c'est ouvert au débat.
la source
(foo() != ERROR)??!??! cerr << "Error occurred" << endl;
5
. Je pense vraiment qu'il y a plus de problème que vous devez faire quelque chose comme ça, alors que dans votre premier exemple, le besoin est assez évident, en particulier dans des choses telles que les gestionnaires de cache.Je pense que les gens sont trop pris dans le "5" que vous revenez ... peut-être que 0 aurait été mieux :)
Quoi qu'il en soit, je pense que le problème est que ce
??!
n'est pas réellement un opérateur autonome. Considérez ce que cela signifierait:Dans ce cas, cela n'a aucun sens: cela n'a de sens que si l'opérande de gauche est un accesseur de propriété. Ou qu'en est-il:
Il y a un accesseur de propriété là-dedans, mais je ne pense toujours pas que cela ait du sens (si
myWidget
ouinull
, cela signifie-t-il que nous n'appelons pasFoo()
du tout?), Ou est-ce juste une erreur?Je pense que le problème est qu'il ne rentre tout simplement pas aussi naturellement dans la langue
??
.la source
Quelqu'un avait créé une classe utilitaire qui ferait cela pour vous. Mais je ne le trouve pas. Ce que j'ai trouvé était quelque chose de similaire sur les forums MSDN (regardez la deuxième réponse).
Avec un peu de travail, vous pouvez l'étendre pour évaluer les appels de méthode et d'autres expressions que l'exemple ne prend pas en charge. Vous pouvez également l'étendre pour accepter une valeur par défaut.
la source
Je comprends d'où tu viens. Il semble que tout le monde s'enroule autour de l'essieu avec l'exemple que vous avez fourni. Bien que je convienne que les nombres magiques sont une mauvaise idée, il y aurait lieu d'utiliser l'équivalent d'un opérateur de coalescence nul pour certaines propriétés.
Par exemple, vous avez des objets liés à une carte et vous souhaitez qu'ils soient à la bonne altitude. Les cartes DTED peuvent avoir des trous dans leurs données, il est donc possible d'avoir une valeur nulle, ainsi que des valeurs de l'ordre de -100 à ~ 8900 mètres. Vous voudrez peut-être quelque chose dans le sens de:
L'opérateur null coallescing dans ce cas remplirait l'altitude par défaut si les coordonnées n'étaient pas encore définies, ou si l'objet coordonnées ne pouvait pas charger les données DTED pour cet emplacement.
Je vois cela comme très précieux, mais mes spéculations sur la raison pour laquelle cela n'a pas été fait se limitent à la complexité du compilateur. Il peut y avoir des cas où le comportement ne serait pas aussi prévisible.
la source
Lorsque je ne traite pas avec des imbrications profondes, j'ai utilisé cela (avant l'opérateur de coalescence nulle introduit en C # 6). Pour moi, c'est assez clair, mais c'est peut-être parce que je suis habitué, d'autres personnes pourraient trouver cela déroutant.
Bien sûr, cela n'est pas toujours applicable, car parfois la propriété à laquelle vous devez accéder ne peut pas être définie directement, ou lorsque la construction de l'objet lui-même est coûteuse, entre autres raisons.
Une autre alternative consiste à utiliser le modèle NullObject . Vous définissez une seule instance statique de la classe avec des valeurs par défaut raisonnables et utilisez-la à la place.
la source
Les nombres magiques ont généralement une mauvaise odeur. Si le 5 est un nombre arbitraire, il est préférable de le préciser afin qu'il soit documenté plus clairement. Une exception à mon avis serait si vous avez une collection de valeurs qui agissent comme des valeurs par défaut dans un contexte particulier.
Si vous avez un ensemble de valeurs par défaut pour un objet, vous pouvez le sous-classer pour créer une instance singleton par défaut.
Quelque chose comme: return (myobj ?? default_obj) .Length
la source
La propriété de longueur est généralement un type de valeur, elle ne peut donc pas être nulle, donc l'opérateur de coalescence nulle n'a pas de sens ici.
Mais vous pouvez le faire avec une propriété qui est un type de référence, par exemple:
var window = App.Current.MainWindow ?? new Window();
la source
J'ai déjà vu quelqu'un avec une idée similaire, mais la plupart du temps, vous souhaitez également affecter la nouvelle valeur dans le champ nul, quelque chose comme:
donc l'idée était de combiner le
??
et l'=
affectation en:Je pense que cela a plus de sens que d'utiliser un point d'exclamation.
Cette idée n'est pas la mienne mais je l'aime vraiment :)
la source
return _obj ?? new Class();
qu'il n'y ait pas besoin de l'??=
ici.