Nullオブジェクトで Any() を呼び出すと、C#でArgumentNullExceptionがスローされます。オブジェクトがnullの場合、間違いなく「any」は存在せず、おそらくfalseを返すはずです。
C#がこのように動作するのはなぜですか?
参照型を扱う場合、null
値は「空の」値と意味的に異なります。
null
文字列はstring.Empty
と同じではなく、null
IEnumerable<T>
はEnumerable.Empty<T>
(またはその他の「空の」列挙可能)とは異なります。そのタイプの)。
Any
が拡張メソッドでない場合、null
で呼び出すとNullReferenceException
になります。それは拡張メソッドであるため、いくつかの例外をスローすることは(必要ではありませんが)良いアイデアですnull
のメソッド:BOOM!
Any()
からの質問:「このボックスにはアイテムが含まれていますか?」
ボックスが空の場合、答えは明らかに「いいえ」です。
しかし、そもそもボックスがなければ、質問は意味をなさず、関数は「一体何のことを言っているのですか?ボックスはありません」と文句を言います。
最新のC#では、次のような簡単なチェックでOPのシナリオを簡単に処理できます。
_List<string> foo = null;
if (foo?.Any() ?? false)
{
DoStuff();
}
_
これは、OPがAnyOrDefault(bool default)
拡張メソッドが行うことを期待している不完全なAny()
実装のようなものです。
これを次のような拡張機能に簡単に作成できます。
_public static bool HasItems<T>(this IEnumerable<T> source)
{
return (source?.Any() ?? false);
}
_
正直なところ、デフォルト値を渡すのは理にかなっていないため、 コメントで提案されているように、AnyOrDefault
という名前はあまり好きではありません(デフォルトのtrueは、おそらく後でコードを読む人にとってはかなり意味があるでしょう)。HasItems
に名前が変更されました。これははるかに良い名前です!
Any()
は拡張メソッドであるため、this
は実際にはメソッドの最初の引数として渡されます。この状況では、ArgumentNullException
is this
is null
をスローすることは理解できます。
事前に自分でチェックを実行できます。
bool hasAny = yourData == null ? false : yourData.Any(yourPredicate);
Any()は次のような拡張メソッドであるため:
public static bool Any(this IEnumerable enumerable)
{
if (enumerable == null)
throw ArgumentNullException("enumerable");
...
}
Any
メソッドはIEnumerable
に対して実行され、アイテムがあるかどうかを示しますEnumerable内。列挙するものを何も与えない場合、ArgumentNullExceptionは妥当です。(一致する)要素のないコレクションは、コレクションがないと異なります。
他の人が既に述べたように、Any
はシーケンスに要素が含まれているかどうかをチェックします。 null
値を渡すことを妨げません(そもそもバグの可能性があります)。
Enumerable
class のすべての拡張メソッドは、ArgumentNullException
がsource
の場合、 null
をスローします。拡張機能でArgumentNullExceptions
をスローするのは、実際には 適切な練習 です。