Как проверить, является ли IEnumerable пустой или пустой?
Мне нравится string.IsNullOrEmpty
метод. Я хотел бы иметь что-то, что позволит использовать те же функции для IEnumerable. Есть такие? Может быть, какой-то класс вспомогательного класса? Причина, по которой я спрашиваю, заключается в том, что в выражениях if
код выглядит загроможденным, если patter равен (mylist != null && mylist.Any())
. Было бы намного чище иметь Foo.IsAny(myList)
.
Это сообщение не дает ответа: IEnumerable пуст?.
Ответы
Ответ 1
Уверен, что мог написать:
public static class Utils {
public static bool IsAny<T>(this IEnumerable<T> data) {
return data != null && data.Any();
}
}
однако будьте осторожны, чтобы не все последовательности повторялись; обычно я предпочитаю только ходить их один раз, на всякий случай.
Ответ 2
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
return enumerable == null || !enumerable.Any();
}
Ответ 3
Здесь приведена модифицированная версия полезного ответа @Matt Greer, которая включает в себя статический класс-оболочку, поэтому вы можете просто скопировать-вставить это в новый исходный файл, не зависит от Linq и добавляет общую перегрузку IEnumerable<T>
, чтобы избегайте бокса типов значений, которые могут возникнуть с нестандартной версией. [EDIT: Обратите внимание, что использование IEnumerable<T>
не предотвращает бокс перечислителя, duck-typing не может этого предотвратить, но, по крайней мере, элементы в значении, типизированная коллекция не будет помещена в коробку.]
using System.Collections;
using System.Collections.Generic;
public static class IsNullOrEmptyExtension
{
public static bool IsNullOrEmpty(this IEnumerable source)
{
if (source != null)
{
foreach (object obj in source)
{
return false;
}
}
return true;
}
public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
{
if (source != null)
{
foreach (T obj in source)
{
return false;
}
}
return true;
}
}
Ответ 4
Другим способом было бы получить Enumerator и вызвать метод MoveNext(), чтобы увидеть, есть ли какие-либо элементы:
if (mylist != null && mylist.GetEnumerator().MoveNext())
{
// The list is not null or empty
}
Это работает для IEnumerable, а также IEnumerable <T> .
Ответ 5
Как я это делаю, используя некоторые современные возможности С#:
Вариант 1)
public static class Utils {
public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
return !(list?.Any() ?? false);
}
}
Вариант 2)
public static class Utils {
public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
return !(list?.Any()).GetValueOrDefault();
}
}
И, кстати, никогда не используйте Count == 0
или Count() == 0
, чтобы проверить, пуста ли коллекция. Всегда используйте Linq .Any()
Ответ 6
Это может помочь
public static bool IsAny<T>(this IEnumerable<T> enumerable)
{
return enumerable?.Any() == true;
}
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
return enumerable?.Any() != true;
}
Ответ 7
Начиная с С# 6 вы можете использовать распространение null: myList?.Any() == true
Если вы все еще находите это слишком засоренным или предпочитаете хороший метод расширения, я бы порекомендовал Matt Greer и Marc Gravell ответы, но с немного расширенной функциональностью для полноты.
Их ответы обеспечивают одну и ту же базовую функциональность, но с другой стороны. Мэтт отвечает string.IsNullOrEmpty
-mentality, тогда как ответ Marc берет путь Linq .Any()
, чтобы выполнить задание.
Я лично склонен использовать .Any()
road, но хотел бы добавить функциональность проверки условий из метода другая перегрузка:
public static bool AnyNotNull<T>(this IEnumerable<T> source, Func<T, bool> predicate = null)
{
if (source == null) return false;
return predicate == null
? source.Any()
: source.Any(predicate);
}
Итак, вы все равно можете делать такие вещи, как:
myList.AnyNotNull(item=>item.AnswerToLife == 42);
, как вы могли бы с помощью обычного .Any()
, но с добавленной нулевой проверкой
Обратите внимание, что с помощью способа С# 6: myList?.Any()
возвращает a bool?
, а не `bool, что является фактическим эффектом распространения null
Ответ 8
Здесь приведен код из ответ Марка Гравелла, а также пример его использования.
using System;
using System.Collections.Generic;
using System.Linq;
public static class Utils
{
public static bool IsAny<T>(this IEnumerable<T> data)
{
return data != null && data.Any();
}
}
class Program
{
static void Main(string[] args)
{
IEnumerable<string> items;
//items = null;
//items = new String[0];
items = new String[] { "foo", "bar", "baz" };
/*** Example Starts Here ***/
if (items.IsAny())
{
foreach (var item in items)
{
Console.WriteLine(item);
}
}
else
{
Console.WriteLine("No items.");
}
}
}
Как он говорит, не все последовательности повторяемы, поэтому код иногда может вызывать проблемы, потому что IsAny()
начинает проходить через последовательность. Я подозреваю, что ответ Роберт Харви означал, что вам часто не нужно проверять null
и пустое. Часто вы можете просто проверить значение null, а затем использовать foreach
.
Чтобы не запускать последовательность дважды и использовать foreach
, я просто написал такой код:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
IEnumerable<string> items;
//items = null;
//items = new String[0];
items = new String[] { "foo", "bar", "baz" };
/*** Example Starts Here ***/
bool isEmpty = true;
if (items != null)
{
foreach (var item in items)
{
isEmpty = false;
Console.WriteLine(item);
}
}
if (isEmpty)
{
Console.WriteLine("No items.");
}
}
}
Я предполагаю, что метод расширения сохраняет несколько строк ввода, но этот код кажется мне более ясным. Я подозреваю, что некоторые разработчики сразу не поймут, что IsAny(items)
действительно начнет проходить через последовательность. (Конечно, если вы используете множество последовательностей, вы быстро научитесь думать о том, какие шаги проходят через них.)
Ответ 9
Я использую Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);
. Надеюсь, это поможет.
Структура:
Collection?.Any()
вернет null
, если Collection имеет значение null, а false
, если коллекция пуста.
Collection?.Any()??false
даст нам false
, если Collection пуст, и false
, если Collection null
.
Дополнение этого даст нам IsEmptyOrNull
.
Ответ 10
if (collection?.Any() == true){
// if collection contains more than one item
}
if (collection?.Any() != true){
// if collection is null
// if collection does not contain any item
}
Ответ 11
Я построил это на основе ответа @Matt Greer
Он отлично ответил на вопрос ОП.
Я хотел что-то подобное, сохраняя при этом исходные возможности Any, а также проверяя на ноль. Я публикую это на тот случай, если кому-то еще понадобится нечто подобное.
В частности, я хотел, чтобы все еще можно было передавать предикат.
public static class Utilities
{
/// <summary>
/// Determines whether a sequence has a value and contains any elements.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">The <see cref="System.Collections.Generic.IEnumerable"/> to check for emptiness.</param>
/// <returns>true if the source sequence is not null and contains any elements; otherwise, false.</returns>
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
{
return source?.Any() == true;
}
/// <summary>
/// Determines whether a sequence has a value and any element of a sequence satisfies a condition.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">An <see cref="System.Collections.Generic.IEnumerable"/> whose elements to apply the predicate to.</param>
/// <param name="predicate">A function to test each element for a condition.</param>
/// <returns>true if the source sequence is not null and any elements in the source sequence pass the test in the specified predicate; otherwise, false.</returns>
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return source?.Any(predicate) == true;
}
}
Возможно, наименование метода расширения могло бы быть лучше.
Ответ 12
У меня была та же проблема, и я решаю ее как:
public bool HasMember(IEnumerable<TEntity> Dataset)
{
return Dataset != null && Dataset.Any(c=>c!=null);
}
"c = > c!= null" игнорирует все пустые объекты.
Ответ 13
просто добавьте using System.Linq
и просмотрите волшебство, когда вы пытаетесь получить доступ к доступным методам в IEnumerable
. Добавление этого параметра даст вам доступ к методу с именем Count()
так просто. просто не забудьте проверить null value
перед вызовом Count()
:)
Ответ 14
Я использовал простой, если его проверить
проверить мое решение
foreach (Pet pet in v.Pets)
{
if (pet == null)
{
Console.WriteLine(" No pet");// enumerator is empty
break;
}
Console.WriteLine(" {0}", pet.Name);
}
Ответ 15
Другое лучшее решение, как ниже, чтобы проверить пусто или нет?
for(var item in listEnumerable)
{
var count=item.Length;
if(count>0)
{
// not empty or null
}
else
{
// empty
}
}
Ответ 16
Я использую это:
public static bool IsNotEmpty(this ICollection elements)
{
return elements != null && elements.Count > 0;
}
Ejem:
List<string> Things = null;
if (Things.IsNotEmpty())
{
//replaces -> if (Things != null && Things.Count > 0)
}
Ответ 17
Поскольку некоторые ресурсы исчерпываются после одного чтения, я подумал, почему бы не объединить проверки и чтения вместо традиционной отдельной проверки, а затем прочитать.
Сначала у нас есть один для более простого встроенного расширения check-for-null:
public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));
var first = source.ThrowOnNull().First();
Тогда нам нужно немного больше (ну, по крайней мере, так, как я это написал) встроенное расширение для проверки на пустое и пустое:
public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
using (var e = source.ThrowOnNull(paramName).GetEnumerator())
{
if (!e.MoveNext())
{
throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
}
do
{
yield return e.Current;
}
while (e.MoveNext());
}
}
var first = source.ThrowOnNullOrEmpty().First();
Конечно, вы можете звонить обоим без продолжения цепочки вызовов. Кроме того, я включил paramName, чтобы вызывающая сторона могла включить альтернативное имя для ошибки, если она не проверяется как "источник", например, "Nameof (цель)".
Ответ 18
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
{
return source != null && source.Any();
}
мой собственный метод расширения, чтобы проверить Не нуль и Любой