web-dev-qa-db-fra.com

Pourquoi Any () ne fonctionne-t-il pas sur un objet nul c #

Lors de l'appel de Any () sur un objet nul, il lève une ArgumentNullException en C #. Si l'objet est nul, il n'y en a certainement pas, et il devrait probablement retourner faux.

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

42
DefenestrationDay

Lorsqu'il s'agit de types de référence, une valeur null est sémantiquement différente d'une valeur "vide".

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

Si Any n'était pas une méthode d'extension, l'appeler sur null entraînerait NullReferenceException. Puisqu'il est une méthode d'extension, lever une exception (bien que non nécessaire) est une bonne idée car elle préserve la sémantique bien connue d'essayer d'appeler un méthode sur null: BOOM!

37
Jon

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."

127
CodesInChaos

Avec le C # moderne, vous pouvez facilement gérer le scénario de l'OP avec une simple vérification comme celle-ci:

List<string> foo = null;

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

C'est un peu comme une implémentation boiteuse de AnyOrDefault(bool default) que l'OP attend de la méthode d'extension Any().

Vous pouvez facilement en faire une extension comme celle-ci:

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

Honnêtement, je n'aime pas vraiment le nom AnyOrDefault pour cela car cela n'aura jamais de sens de passer une valeur par défaut (une valeur par défaut true serait probablement assez méchante pour les personnes qui liront du code plus tard). Renommé en HasItems, comme suggéré dans les commentaires. C'est un bien meilleur nom!

32
Jaxidian

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

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

bool hasAny = yourData == null ? false : yourData.Any(yourPredicate);
4
Frédéric Hamidi

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

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

La méthode Any s'exécute sur un IEnumerable et vous indique s'il existe des éléments dans l'énumérable. Si vous ne lui donnez rien à énumérer, une ArgumentNullException est raisonnable: une collection sans élément (correspondant) est différente de no collecion.

1
Dan Puzey

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 des valeurs null (quel pourrait être le bogue en premier lieu).

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

1
Tim Schmelter