Does C# have IsNullOrEmpty for List/IEnumerable?

前端 未结 10 439
一生所求
一生所求 2020-12-23 11:04

I know generally empty List is more prefer than NULL. But I am going to return NULL, for mainly two reasons

  1. I have to check and handle null values explicitly,
相关标签:
10条回答
  • 2020-12-23 11:32
    var nullOrEmpty = list == null || !list.Any();
    
    0 讨论(0)
  • 2020-12-23 11:34

    I modified the suggestion from Matthew Vines to avoid the "Possible multiple enumeration of IEnumerable" - problem. (see also the comment from Jon Hanna)

    public static bool IsNullOrEmpty(this IEnumerable items)
        => items == null
        || (items as ICollection)?.Count == 0
        || !items.GetEnumerator().MoveNext();
    

    ... and the unit test:

    [Test]
    public void TestEnumerableEx()
    {
        List<int> list = null;
        Assert.IsTrue(list.IsNullOrEmpty());
    
        list = new List<int>();
        Assert.IsTrue(list.IsNullOrEmpty());
    
        list.AddRange(new []{1, 2, 3});
        Assert.IsFalse(list.IsNullOrEmpty());
    
        var enumerator = list.GetEnumerator();
        for(var i = 1; i <= list.Count; i++)
        {
            Assert.IsFalse(list.IsNullOrEmpty());
            Assert.IsTrue(enumerator.MoveNext());
            Assert.AreEqual(i, enumerator.Current);
        }
    
        Assert.IsFalse(list.IsNullOrEmpty());
        Assert.IsFalse(enumerator.MoveNext());
    }
    
    0 讨论(0)
  • 2020-12-23 11:36

    There is nothing built in.

    It is a simple extension method though:

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
    {
      if(enumerable == null)
        return true;
    
      return !enumerable.Any();
    }
    
    0 讨论(0)
  • 2020-12-23 11:37

    As everyone else has said, nothing is built into the framework, but if you are using Castle then Castle.Core.Internal has it.

    using Castle.Core.Internal;
    
    namespace PhoneNumbers
    {
        public class PhoneNumberService : IPhoneNumberService
        {
            public void ConsolidateNumbers(Account accountRequest)
            {
                if (accountRequest.Addresses.IsNullOrEmpty()) // Addresses is List<T>
                {
                    return;
                }
                ...
    
    0 讨论(0)
  • 2020-12-23 11:42

    nothing baked into the framework, but it's a pretty straight forward extension method.

    See here

    /// <summary>
        /// Determines whether the collection is null or contains no elements.
        /// </summary>
        /// <typeparam name="T">The IEnumerable type.</typeparam>
        /// <param name="enumerable">The enumerable, which may be null or empty.</param>
        /// <returns>
        ///     <c>true</c> if the IEnumerable is null or empty; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
        {
            if (enumerable == null)
            {
                return true;
            }
            /* If this is a list, use the Count property for efficiency. 
             * The Count property is O(1) while IEnumerable.Count() is O(N). */
            var collection = enumerable as ICollection<T>;
            if (collection != null)
            {
                return collection.Count < 1;
            }
            return !enumerable.Any(); 
        }
    

    Daniel Vaughan takes the extra step of casting to ICollection (where possible) for performance reasons. Something I would not have thought to do.

    0 讨论(0)
  • 2020-12-23 11:42

    Late update: since C# 6.0, the null-propagation operator may be used to express concise like this:

    if (  list?.Count  > 0 ) // For List<T>
    if ( array?.Length > 0 ) // For Array<T>
    

    or, as a cleaner and more generic alternative for IEnumerable<T>:

    if ( enumerable?.Any() ?? false )
    

    Note 1: all upper variants reflect actually IsNotNullOrEmpty, in contrast to OP question (quote):

    Because of operator precedence IsNullOrEmpty equivalents look less appealing:
    if (!(list?.Count > 0))

    Note 2: ?? false is necessary, because of the following reason (summary/quote from this post):

    ?. operator will return null if a child member is null. But [...] if we try to get a non-Nullable member, like the Any() method, that returns bool [...] the compiler will "wrap" a return value in Nullable<>. For example, Object?.Any() will give us bool? (which is Nullable<bool>), not bool. [...] Since it can't be implicitly casted to bool this expression cannot be used in the if

    Note 3: as a bonus, the statement is also "thread-safe" (quote from answer of this question):

    In a multithreaded context, if [enumerable] is accessible from another thread (either because it's a field that's accessible or because it's closed over in a lambda that is exposed to another thread) then the value could be different each time it's computed [i.e.prior null-check]

    0 讨论(0)
提交回复
热议问题