Est-il déraisonnable de s’attendre à ce que Any () * not * lève une exception de référence nulle?

41

Lorsque vous créez une méthode d'extension , vous pouvez, bien sûr, appelez sur null.Mais, contrairement à un appel d'instance de méthode, l' appelant sur null ne pas avoir à jeter un NullReferenceException-> vous devez vérifier et de le jeter manuellement.

Pour l’implémentation de la méthode d’extension Linq, Any()Microsoft a décidé d’envoyer une ArgumentNullException( https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/AnyAll.cs ).

Ça m'irrite d'avoir à écrire if( myCollection != null && myCollection.Any() )

Ai-je tort, en tant que client de ce code, de penser que, par exemple, ((int[])null).Any()devrait revenir false?

cette fin
la source
41
en C # 6, vous pouvez simplifier votre contrôle en vérifiant si (myCollection? .Any () == true)
17 sur 26
5
Même en F #, qui n'utilise pas vraiment de valeurs NULL, à l'exception de l'interopérabilité avec d'autres langages .NET, null |> Seq.isEmptyrenvoie System.ArgumentNullException: Value cannot be null. L'attente semble être que vous ne passerez pas de valeurs indéfinies pour quelque chose qui devrait exister, c'est donc toujours une exception lorsque vous avez un null. Si c'est une question d'initialisation, je commencerais par une séquence vide au lieu d'un null.
Aaron M. Eshbach
21
C'est pourquoi vous ne devez pas retourner nulllorsque vous traitez avec des collections, mais utilisez plutôt une collection vide dans ces cas.
Bakuriu
31
Eh bien pourquoi est-il nul en premier lieu? Vous ne voulez pas que null soit considéré comme vide, car ce n'est pas vide, c'est quelque chose de complètement différent. Peut-être voulez-vous qu'il soit considéré comme vide dans votre cas, mais l'ajout de ce genre de chose à la langue conduit à des bugs.
user253751
22
Je dois souligner que chaque méthode LINQ jette un argument nul. Anyest juste cohérent.
Sebastian Redl

Réponses:

157

J'ai un sac avec cinq pommes de terre dedans. Y a-t-il des .Any()pommes de terre dans le sac?

" Oui " , dites-vous.<= true

Je sors toutes les pommes de terre et les mange. Y a-t-il des .Any()pommes de terre dans le sac?

" Non " , dites-vous.<= false

J'incinère complètement le sac dans un feu. Y at-il des .Any()pommes de terre dans le sac maintenant?

" Il n'y a pas de sac ."<= ArgumentNullException

Dan Wilson
la source
3
Mais vide, il n'y a pas de pommes de terre dans le sac? False implique False ... (je ne suis pas en désaccord, mais une seconde perspective).
D. Ben Knoble
6
plus concrètement, quelqu'un vous remet une boîte fermée d'origine inconnue. Le sac dans la boîte contient-il des pommes de terre? Je ne suis intéressé que par 2 scénarios - A) il y a un sac dans la boîte qui contient des pommes de terre, ou B) il n'y a pas de pommes de terre et / ou pas de sac dans la boîte. Sémantiquement, oui, il y a une différence entre nul et vide, mais 99% du temps, cela m'est égal.
Dave Thieben
6
Vous avez mangé cinq pommes de terre crues? Demander de l'aide médicale immédiatement.
Oly
3
@Oly Dan les a fait cuire au feu, avant de manger et d'utiliser ce feu pour incinérer le sac.
Ismael Miguel
3
@ D.BenKnoble: Sans avoir vu le coffre de ma voiture, êtes-vous prêt à témoigner qu'il n'y a pas de corps dans le coffre de ma voiture? Non? Quelle est la différence entre vérifier le coffre et ne rien trouver ou ne pas vérifier le coffre? Ne pouvez-vous pas simplement témoigner maintenant, puisque vous auriez vu exactement le même nombre de corps dans les deux cas? ... c'est la différence. Vous ne pouvez pas garantir quelque chose si vous n'êtes pas en mesure de le confirmer au départ. Vous supposez que les deux sont équivalents, mais ce n'est pas une donnée. Dans certains cas, il peut y avoir une différence importante entre les deux.
Flater
52

Tout d'abord, il semble que ce code source va lancer ArgumentNullException, non NullReferenceException.

Cela dit, dans de nombreux cas, vous savez déjà que votre collection n'est pas nulle, car ce code est appelé uniquement à partir d'un code qui sait que la collection existe déjà. Vous n'aurez donc pas à y mettre très souvent la vérification de la valeur NULL. Mais si vous ne savez pas qu’il existe, il est alors logique de vérifier avant de faire appel Any()à celui-ci.

Ai-je tort, en tant que client de ce code, de penser que, par exemple, ((int[])null).Any()devrait revenir false?

Oui. La question qui Any()répond est "cette collection contient-elle des éléments?" Si cette collection n'existe pas, alors la question elle-même est insensée; il ne peut ni contenir ni ne rien contenir, car il n'existe pas.

Maçon Wheeler
la source
18
@ChrisWohlert: Votre intuition m'intrigue. Pensez-vous également que sémantiquement, une personne inexistante est une personne vide, dont le nom est la chaîne vide et dont l'âge est égal à zéro et ainsi de suite? Et pensez-vous qu'un ensemble contenant nullest équivalent à un ensemble contenant l'ensemble vide (et inversement)?
Ruakh
17
@ChrisWohlert: Évidemment, un ensemble peut contenir l'ensemble vide. mais vous semblez croire cela { null }et { {} }devrait être équivalent. Je trouve cela fascinant. Je ne peux pas comprendre du tout.
Ruakh
9
Doit- .Addon en nullquelque sorte créer une collection pour nous aussi?
Matthieu
13
@ChrisWohlert "A est un ensemble vide. B est un ensemble contenant une pastèque. Est-ce qu'un A est vide? Oui. Est-ce que B est vide? Non. Est-ce que C est vide? Uhhh ..."
user253751
16
Point pédant: En théorie des ensembles, un ensemble non existant n'est pas un ensemble vide. L'ensemble vide existe, et aucun ensemble non-existant ne l'est pas (et n'est en réalité rien du tout, puisqu'il n'existe pas).
James_pic le
22

Null signifie informations manquantes, pas aucun élément.

Vous pourriez envisager plus généralement d'éviter NULL. Par exemple, utilisez l'un des énumérables vides intégrés pour représenter une collection sans élément au lieu de null.

Si vous renvoyez null dans certaines circonstances, vous pouvez changer cela pour renvoyer la collection vide. (Sinon, si vous trouvez que null est renvoyé par des méthodes de bibliothèque (pas la vôtre), c'est dommage, et je les envelopperai pour les normaliser.)

Voir aussi https://stackoverflow.com/questions/1191919/what-does-linq-return-when-the-results-are-empty

Erik Eidt
la source
1
Cela nullne veut pas dire qu’aucun élément est une question de convention raisonnable. Il suffit de penser OLESTRINGS indigènes, où il fait exerce ses signifient que.
Déduplicateur
1
@DuDuplicator, parlez-vous de la liaison et de l'incorporation d'objets de Microsoft? Si vous êtes rappelez-vous que OLE est des années 90! De plus, de nombreux langages modernes (C #, Java, Swift) fournissent des fonctionnalités pour éliminer / éliminer les utilisations de null.
Erik Eidt
2
@ErikEidt Ils le font, en partie, parce que nullcela ne signifie pas "informations manquantes". nulln'a pas une seule interprétation significative. Au lieu de cela, il s'agit de savoir comment vous le traitez. nullest parfois utilisé pour "informations manquantes", mais aussi pour "aucun élément", ainsi que pour "une erreur est survenue" ou "non initialisé" ou "conflit d'informations" ou quelque chose d'arbitraire, ad hoc.
Derek Elkins
-1. C'est une décision prise par le développeur, pas par des théories abstraites. nullest très fréquemment utilisé pour signifier "pas de données". Parfois, cela a du sens. D'autres fois, pas.
Jpmc26 le
13

Outre la syntaxe null-conditionnelle , il existe une autre technique permettant de résoudre ce problème: ne laissez jamais votre variable null.

Considérons une fonction qui accepte une collection en tant que paramètre. Si pour les besoins de la fonction, nullet vide sont équivalents, vous pouvez vous assurer qu’il ne contient jamais nullau début:

public MyResult DoSomething(int a, IEnumerable<string> words)
{
    words = words ?? Enumerable.Empty<string>();

    if (!words.Any())
    {
        ...

Vous pouvez faire la même chose lorsque vous récupérez des collections à partir d'une autre méthode:

var words = GetWords() ?? Enumerable.Empty<string>();

(Notez que dans les cas où vous avez le contrôle d'une fonction similaire à la collection vide GetWordset nulléquivalente à celle-ci, il est préférable de renvoyer la collection vide en premier lieu.)

Vous pouvez maintenant effectuer toute opération de votre choix sur la collection. Ceci est particulièrement utile si vous devez effectuer de nombreuses opérations qui échoueraient lors de la collecte null. Dans les cas où vous obtiendrez le même résultat en effectuant une boucle ou en interrogeant un énumérable vide, cela permettra d'éliminer ifcomplètement les conditions.

jpmc26
la source
12

Ai-je tort, en tant que client de ce code, de s'attendre à ce que par exemple ((int []) null) .Any () renvoie false?

Oui, tout simplement parce que vous êtes en C # et que ce comportement est bien défini et documenté.

Si vous construisiez votre propre bibliothèque ou si vous utilisiez une langue différente avec une culture d'exception différente, il serait plus raisonnable de s'attendre à une valeur fausse.

Personnellement, j’ai l’impression que return false est une approche plus sûre qui rend votre programme plus robuste, mais au moins discutable.

Telastyn
la source
15
Cette "robustesse" est souvent une illusion: si le code qui génère le tableau commence soudainement à générer des valeurs NULL en raison d'un bogue ou d'un autre problème, votre code "robuste" masque le problème. C'est un comportement approprié parfois, mais ce n'est pas un comportement sûr.
GoatInTheMachine le
1
@GoatInTheMachine - Je ne suis pas d'accord sur le fait qu'il s'agisse d'un paramètre par défaut sécurisé, mais vous avez raison de dire qu'il cache le problème et qu'un tel comportement est parfois indésirable. D'après mon expérience, il est préférable de cacher le problème (ou de faire confiance aux tests unitaires pour détecter les problèmes d'autres codes) plutôt que de bloquer votre application en lançant des exceptions inattendues. Je veux dire vraiment - si le code d'appel est suffisamment cassé pour envoyer des nulls, quelle est la chance qu'ils gèrent les exceptions correctement?
Telastyn
10
Si quelque chose est brisé, qu'il s'agisse de mon code, d'un autre collègue ou d'un client, je préférerais que le code échoue immédiatement et que les gens le sachent qu'il continue dans un état potentiellement incohérent pendant une durée indéterminée. Pouvoir faire cela est bien sûr parfois un luxe et pas toujours approprié mais c'est l'approche que je préfère.
GoatInTheMachine le
1
@GoatInTheMachine - Je suis d'accord pour beaucoup de choses, mais les collections ont tendance à être différentes. Traiter null comme une collection vide n'est pas un comportement terriblement incohérent ou surprenant.
Telastyn
8
Imaginez que vous ayez un tableau rempli à partir d'un document JSON reçu via une requête Web et qu'en production, l'un des clients de votre API rencontre soudainement un problème: il envoie un fichier JSON partiellement invalide, ce qui vous oblige à désérialiser un tableau comme étant NULL. dans le pire des cas, le code a généré une exception de référence NULL au moment de l'entrée de la première requête incorrecte, ce que vous voyez dans la journalisation puis demandez immédiatement au client de corriger ses requêtes rompues, OU votre code indique "oh, le tableau est vide, rien faire!" et silencieusement écrit «panier d'achat n'a pas d'articles» à la base de données pendant quelques semaines?
GoatInTheMachine
10

Si les vérifications nulles répétées vous importunent, vous pouvez créer votre propre méthode d'extension 'IsNullOrEmpty ()', afin de refléter la méthode String de ce nom et regrouper les appels null-check et .Any () dans un seul appel.

Sinon, la solution, mentionnée par @ 17 sur 26 dans un commentaire sous votre question, est également plus courte que la méthode "standard" et est raisonnablement claire pour les personnes familiarisées avec la nouvelle syntaxe null-conditionnelle.

if(myCollection?.Any() == true)
Theo Brinkman
la source
4
Vous pouvez également utiliser ?? falseau lieu de == true. Cela me semblerait plus explicite (plus net) car il ne traite que le cas de null, et ce n'est plus vraiment verbeux. De plus, les ==contrôles pour les booléens déclenchent généralement mon réflexe nauséeux. =)
jpmc26 le
2
@ jpmc26: Je ne connais pas grand chose en C #. Pourquoi pas myCollection?.Any()assez?
Eric Duminil le
6
@EricDuminil En raison de la manière dont fonctionne l'opérateur null-conditionnel, myCollection?.Any()retourne effectivement un booléen nullable plutôt qu'un booléen ordinaire (c'est-à-dire bool? Au lieu de bool). Il n'y a pas de conversion implicite de bool? bool, et c'est un bool nous avons besoin dans cet exemple particulier (pour tester dans le cadre de la ifcondition). Par conséquent, nous devons soit explicitement comparer, truesoit utiliser l’opérateur de coalescence nulle (??).
Steven Rands le
@ jpmc26 ?? false est plus difficile à lire que myCollection? .Any () == true. Indépendamment de votre réflexe nauséeux, == true est ce que vous essayez de tester implicitement. ?? false ajoute simplement du bruit supplémentaire et vous devez toujours évaluer dans votre tête ce qui se passe si la valeur est null, que null == true échouera, presque sans que le lecteur ait même à être au courant ?..
Ryan The Leach
2
@RyanTheLeach Je dois réfléchir beaucoup plus avant pour savoir si ==cela fonctionnera réellement. Je sais déjà ce qui se passe avec un booléen intuitivement quand il ne peut être que trueou false; Je n'ai même pas à y penser. Mais ajoutons nullà cela, et maintenant je dois déterminer si c'est ==correct. ??au lieu de cela, élimine simplement le nullcas, le ramenant à trueet falseque vous comprenez déjà immédiatement. En ce qui concerne mon réflexe nauséeux, lorsque je le vois pour la première fois, mon instinct immédiat est de simplement le supprimer car il est généralement inutile, ce que vous ne voulez pas voir se produire.
jpmc26
8

Ai-je tort, en tant que client de ce code, de s'attendre à ce que par exemple ((int []) null) .Any () renvoie false?

Si vous vous interrogez sur les attentes, vous devez réfléchir aux intentions.

null signifie quelque chose de très différent de Enumerable.Empty<T>

Comme mentionné dans la réponse d'Erik Eidt , il existe une différence de sens entre nullune collection vide.

Voyons d'abord comment ils sont censés être utilisés.

Le livre intitulé Framework Design Guidelines: Conventions, idiomes et modèles pour les bibliothèques .NET réutilisables, 2e édition, rédigé par les architectes de Microsoft, Krzysztof Cwalina et Brad Abrams, décrit la meilleure pratique suivante:

X NE PAS renvoyer de valeurs NULL à partir de propriétés de collection ou de méthodes renvoyant des collections. Retourne une collection vide ou un tableau vide à la place.

Envisagez d’appeler une méthode qui consiste à extraire des données d’une base de données: si vous recevez un tableau vide ou si Enumerable.Empty<T>cela signifie simplement que votre espace d’échantillon est vide, le résultat est un ensemble vide . Recevoir nulldans ce contexte signifierait cependant un état d'erreur .

Dans le même ordre d'idées que l'analogie de Dan Wilson en matière de pommes de terre , il est logique de poser des questions sur vos données, même s'il s'agit d'un ensemble vide . Mais cela a beaucoup moins de sens, s’il n’ya pas de décor .

Søren D. Ptæus
la source
1
Leur sens différent dépend fortement du contexte. Souvent, pour les besoins de la logique, ils représentent des concepts équivalents. Pas toujours , mais souvent.
jpmc26
1
@ jpmc26: Je pense que le but de cette réponse est de dire qu'en codant les instructions pour c #, elles ont un sens différent. Vous pouvez toujours rectifier le code où null et vide sont identiques si vous le souhaitez. Et dans certains cas, vous pouvez également faire la même chose, qu’elle soit nulle ou vide, mais cela ne signifie pas qu’ils signifient la même chose.
Chris
@Chris Et je dis que les directives de codage des personnes qui ont conçu le langage ne peuvent pas remplacer l'évaluation de votre code dans le contexte de vos besoins, des bibliothèques que vous utilisez et des autres développeurs avec lesquels vous travaillez. L'idée qu'ils ne seront jamais équivalents dans le contexte est un idéalisme sans scrupule. Elles pourraient même ne pas être équivalentes pour les données disponibles en général, mais être équivalentes pour générer un résultat dans une fonction spécifique que vous écrivez; dans ce cas, vous devez prendre en charge les deux mais assurez-vous qu'ils génèrent le même résultat.
jpmc26
Je suis peut-être dérouté par ce que vous dites, mais lorsque null et empty sont équivalents pour générer un résultat, je ne vois pas pourquoi vous n'utiliseriez pas simplement des éléments séparés, c'est null et des contrôles vides plutôt que de vouloir une méthode qui fait les deux à la fois mais ne vous permet pas de les distinguer dans d'autres situations ...
Chris
@Chris Je parle de contextes différents (qui correspondent souvent à des portées). Considérons une fonction par exemple. nullet empty peut entraîner la même valeur de retour pour la fonction, mais cela ne signifie pas que nullet vide signifie exactement la même chose dans l'étendue de l'appel.
jpmc26
3

Il existe de nombreuses réponses expliquant pourquoi nullet vide sont des opinions différentes et suffisamment nombreuses pour tenter d’ expliquer à la fois pourquoi elles devraient être traitées différemment ou non. Cependant, vous demandez:

Ai-je tort, en tant que client de ce code, de s'attendre à ce que par exemple ((int []) null) .Any () renvoie false?

C'est une attente parfaitement raisonnable . Vous avez aussi raison que quelqu'un qui préconise le comportement actuel. Je suis d'accord avec la philosophie de mise en œuvre actuelle, mais les facteurs déterminants ne sont pas - uniquement - fondés sur des considérations hors contexte.

Étant donné que Any()sans prédicat est essentiellement Count() > 0alors qu'attendez-vous de cet extrait?

List<int> list = null;
if (list.Count > 0) {}

Ou un générique:

List<int> list = null;
if (list.Foo()) {}

Je suppose que vous vous attendez NullReferenceException.

  • Any()est une méthode d’extension, elle doit s’intégrer harmonieusement à l’ objet étendu puis le lancement d’une exception est la moins surprenante.
  • Tous les langages .NET ne prennent pas en charge les méthodes d'extension.
  • Vous pouvez toujours appeler Enumerable.Any(null)et vous vous attendez certainement ArgumentNullException. C'est la même méthode et elle doit être compatible avec - peut-être - presque TOUT le reste du Cadre.
  • L'accès à un nullobjet est une erreur de programmation , le framework ne devant pas appliquer null comme valeur magique . Si vous l'utilisez de cette façon, il vous incombe de vous en occuper.
  • C'est une opinion , vous pensez d'une manière et je pense d'une autre manière. Le cadre devrait être aussi peu avisé que possible.
  • Si vous avez un cas particulier, alors vous devez être cohérent : vous devez prendre de plus en plus de décisions sur toutes les autres méthodes d'extension: si cela Count()semble une décision facile, il Where()ne l'est pas. Qu'en est- il Max()? Il jette une exception pour une liste VIDE, ne devrait-il pas aussi en lancer nullune?

Ce que les concepteurs de bibliothèque ont fait avant LINQ était d'introduire des méthodes explicites lorsqu'une valeur nullest valide (par exemple String.IsNullOrEmpty()), ils doivent ensuite être cohérents avec la philosophie de conception existante . Cela dit, même si assez trivial à écrire, deux méthodes EmptyIfNull()et EmptyOrNull()peut - être à portée de main.

Adriano Repetti
la source
1

Jim est supposé laisser des pommes de terre dans chaque sac. Sinon je vais le tuer.

Jim a un sac contenant cinq pommes de terre. Y a-t-il des .Any()pommes de terre dans le sac?

"Oui", dites-vous. <= vrai

Ok, Jim vit cette fois.

Jim prend toutes les pommes de terre et les mange. Existe-t-il des pommes de terre dans le sac?

"Non", dites-vous. <= faux

Il est temps de tuer Jim.

Jim incinère complètement le sac dans un feu. Existe-t-il des pommes de terre dans le sac?

"Il n'y a pas de sac." <= ArgumentNullException

Jim doit-il vivre ou mourir? Nous ne nous attendions pas à cela, alors j’ai besoin d’une décision. Est-ce que laisser Jim s'en tirer avec ça est un bug ou pas?

Vous pouvez utiliser des annotations pour signaler que vous n'acceptez pas de mannequins nuls de cette façon.

public bool Any( [NotNull] List bag ) 

Mais votre chaîne d’outils doit le supporter. Ce qui signifie que vous finirez probablement par écrire des chèques.

confits_orange
la source
0

Si cela vous dérange tellement, je suggère une méthode d'extension simple.

static public IEnumerable<T> NullToEmpty<T>(this IEnumerable<T> source)
{
    return (source == null) ? Enumerable.Empty<T>() : source;
}

Maintenant vous pouvez faire ceci:

List<string> list = null;
var flag = list.NullToEmpty().Any( s => s == "Foo" );

... et le drapeau sera réglé sur false.

John Wu
la source
2
Il est plus naturel d'écrire cette returndéclaration en tant que:return source ?? Enumerable.Empty<T>();
Jeppe Stig Nielsen le
Cela ne répond pas à la question posée.
Kenneth K.
@ KennethK. Mais cela semble résoudre le problème présenté.
RQDQ
0

Il s’agit d’une question sur les méthodes d’extension de C # et leur philosophie de conception. Je pense donc que le meilleur moyen de répondre à cette question est de citer la documentation de MSDN sur les méthodes d’extension :

Les méthodes d'extension vous permettent d '"ajouter" des méthodes à des types existants sans créer de nouveau type dérivé, recompiler ou modifier le type d'origine. Les méthodes d'extension sont un type spécial de méthode statique, mais elles sont appelées comme s'il s'agissait de méthodes d'instance sur le type étendu. Pour le code client écrit en C #, F # et Visual Basic, il n'y a pas de différence apparente entre l'appel d'une méthode d'extension et les méthodes réellement définies dans un type.

En général, nous vous recommandons d'implémenter les méthodes d'extension avec parcimonie et uniquement lorsque vous devez le faire. Dans la mesure du possible, le code client qui doit étendre un type existant doit le faire en créant un nouveau type dérivé du type existant. Pour plus d'informations, voir Héritage.

Lorsque vous utilisez une méthode d'extension pour étendre un type dont le code source ne peut pas être modifié, vous courez le risque qu'une modification de l'implémentation du type entraîne la rupture de votre méthode d'extension.

Si vous implémentez des méthodes d'extension pour un type donné, souvenez-vous des points suivants:

  • Une méthode d'extension ne sera jamais appelée si elle a la même signature qu'une méthode définie dans le type.
  • Les méthodes d'extension sont incluses dans la portée au niveau de l'espace de noms. Par exemple, si vous avez plusieurs classes statiques contenant des méthodes d’extension dans un seul espace-noms nomméExtensions , elles seront toutes portées à la portée de la using Extensions;directive.

Pour résumer, les méthodes d'extension sont conçues pour ajouter des méthodes d'instance à un type particulier, même lorsque les développeurs ne peuvent pas le faire directement. Et parce que les méthodes d'instance vont remplacent toujours les méthodes d'extension si elles sont présentes (si elles sont appelées à l'aide de la syntaxe de méthode d'instance), vous ne devez le faire que si vous ne pouvez pas ajouter directement de méthode ou étendre la classe. *

En d'autres termes, une méthode d'extension doit agir comme une méthode d'instance, car elle peut être transformée en méthode d'instance par un client. Et parce qu'une méthode d'instance doit lancer si l'objet sur lequel il est appelé estnull , la méthode d'extension devrait l'être également.


* Comme une note de côté, c'est exactement la situation que les concepteurs de LINQ face: quand C # 3.0 est sorti, il y avait déjà des millions de clients qui utilisaient System.Collections.IEnumerableet System.Collections.Generic.IEnumerable<T>, à la fois dans leurs collections et en foreachboucles. Ces classes sont revenus des IEnumeratorobjets qui n'avaient les deux méthodes Currentet MoveNext, afin d' ajouter des méthodes d'instance supplémentaires nécessaires, commeCount , Any, etc., enfreindrait ces millions de clients. Ainsi, afin de fournir cette fonctionnalité ( en particulier car il peut être mis en œuvre en termes de Currentet MoveNextavec une relative facilité), ils sortent comme des méthodes d'extension, qui peuvent être appliquées à tout moment existanteIEnumerableexemple et peut également être implémenté par les classes de manière plus efficace. Si les concepteurs de C # avaient décidé de publier LINQ dès le premier jour, cela aurait été fourni comme méthode d'instance IEnumerableet ils auraient probablement conçu un système pour fournir des implémentations d'interface par défaut de ces méthodes.

TheHinsinator
la source
0

Je pense que l’essentiel ici est qu’en renvoyant la valeur false au lieu de lever une exception, vous masquerez les informations pouvant présenter un intérêt pour les futurs lecteurs / modificateurs de votre code.

S'il est possible que la liste soit nulle, je suggérerais d'avoir un chemin logique séparé pour cela, car sinon, à l'avenir, quelqu'un pourrait ajouter une logique basée sur une liste (comme un ajout) à else {} de votre if, entraînant ainsi une exception non désirée qu’ils n’ont aucune raison de prédire.

La lisibilité et la maintenabilité sont des atouts majeurs: «Je dois écrire une condition supplémentaire» à chaque fois.

Callum Bradbury
la source
0

En règle générale, j'écris l'essentiel de mon code pour supposer que l'appelant est responsable de ne pas me transmettre de données nulles, principalement pour les raisons décrites dans Dites non à nul (et autres publications similaires). Le concept de null est souvent mal compris et, pour cette raison, il est conseillé d’initialiser vos variables à l’avance, autant que possible. En supposant que vous travailliez avec une API raisonnable, vous devriez idéalement ne jamais récupérer une valeur null. Vous ne devriez donc jamais avoir à vérifier la valeur null. Le point null, comme d'autres réponses l'ont indiqué, est de vous assurer que vous disposez d'un objet valide (par exemple, un "sac") avec lequel travailler avant de continuer. Ce n'est pas une fonctionnalité de Any, mais plutôt une fonctionnalité de la languelui-même. Vous ne pouvez pas effectuer la plupart des opérations sur un objet null, car il n'existe pas. C'est comme si je vous demandais de conduire au magasin avec ma voiture, sauf que je ne possède pas de voiture, vous n'avez donc aucun moyen d'utiliser ma voiture pour aller au magasin. Il est absurde de faire une opération sur quelque chose qui n'existe pas littéralement.

Il existe des cas pratiques d'utilisation de null, par exemple lorsque vous ne disposez littéralement pas des informations demandées (par exemple, si je vous ai demandé quel est mon âge, le choix le plus probable pour vous de répondre à ce stade est "Je ne sais pas ", qui est ce qu’une valeur nulle est). Cependant, dans la plupart des cas, vous devriez au moins savoir si vos variables sont initialisées ou non. Et si vous ne le faites pas, alors je vous recommanderais de resserrer votre code. La première chose que je fais dans un programme ou une fonction est d’initialiser une valeur avant de l’utiliser. Il est rare que je doive vérifier les valeurs NULL, car je peux garantir que mes variables ne sont pas nulles. C'est une bonne habitude à prendre, et plus vous vous rappelez d'initialiser vos variables fréquemment, moins vous devez vérifier la valeur null.

Phyrfox
la source