Question Pourquoi Any () ne fonctionne pas sur un objet c # null


En appelant Tout() sur un objet nul, il émet une ArgumentNullException en C #. Si l'objet est nul, il n'y a certainement pas de "aucun", et il devrait probablement retourner false.

Pourquoi C # se comporte-t-il de cette façon?


28
2017-07-18 09:26


origine


Réponses:


Lorsque vous traitez des types de référence, un null la valeur est sémantiquement différente d'une valeur "vide".

UNE null la chaîne n'est pas la même que string.Emptyet un null  IEnumerable<T> n'est pas la même que Enumerable.Empty<T> (ou tout autre énumérable "vide" de ce type).

Si Any n'étaient pas une méthode d'extension, l'appelant sur null aboutirait à NullReferenceException. Puisqu'il est une méthode d'extension, lancer des exceptions (bien que pas nécessaire) est une bonne idée car elle préserve la sémantique bien connue consistant à essayer d'appeler une méthode sur null: BOOM!


26
2017-07-18 09:30



Any() demande: "Cette boîte contient-elle des éléments?"

Si la case est vide, la réponse est clairement non.

Mais s'il n'y a pas de boîte en premier lieu, alors la question n'a aucun sens, et la fonction se plaint: "De quoi parlez-vous? Il n'y a pas de boîte."


95
2017-07-18 09:30



Avec le C # moderne, vous pouvez facilement gérer le scénario des OP avec une simple vérification comme ceci:

List<string> foo = null;

if (foo?.Any() ?? false)
{
    DoStuff();
}

C'est un peu comme un boiteux AnyOrDefault(bool default) la mise en œuvre que le PO attend la Any() méthode d'extension à faire.

Vous pourriez facilement en faire une extension comme ceci:

public static bool AnyOrDefault<T>(this IEnumerable<T> source)
{
    return (source?.Any() ?? false);
}

Honnêtement, je n'aime pas vraiment le nom AnyOrDefault pour cela, il ne sera jamais logique de passer une valeur par défaut (une valeur par défaut de true serait probablement plutôt méchante pour les lecteurs de code plus tard).


5
2017-10-11 14:19



Any() est une méthode d'extension, donc this est en fait passé comme premier argument de la méthode. Dans cette situation, il est compréhensible de jeter ArgumentNullException est this est null.

Vous pouvez effectuer le contrôle vous-même au préalable:

bool hasAny = yourData == null ? false : yourData.Any(yourPredicate);

4
2017-07-18 09:29



le Any la méthode court contre un IEnumerable et vous indique s'il y a des articles dans le Enumerable. Si vous ne lui donnez rien à énumérer, une ArgumentNullException est raisonnable: une collection sans éléments (correspondants) est différente de pas de collecion.


1
2017-07-18 09:28



Parce que Any () c'est une méthode d'extension comme ceci:

public static bool Any(this IEnumerable enumerable)
{
    if (enumerable == null)
        throw ArgumentNullException("enumerable");
    ...
}

1
2017-07-18 09:36



Comme d'autres l'ont déjà mentionné, Any vérifie si une séquence contient ou non des éléments. Cela ne vous empêche pas de passer null valeurs (ce que le bogue pourrait avoir en premier lieu).

Chaque méthode d'extension dans Enumerable classe jette un an ArgumentNullException si la source est null. Lancement ArgumentNullExceptions dans les extensions est en fait bonne pratique.


1
2017-07-18 09:36