Click here to Skip to main content
15,887,970 members
Articles / Programming Languages / C#

IsNullOrEmpty for Generic Collections in C#

,
Rate me:
Please Sign up or sign in to vote.
3.43/5 (18 votes)
12 Aug 2015CPOL 33.6K   11   22
IsNullOrEmpty for Generic Collections in C#

In this code snippet, we will see the creation and implementation of IsNullOrEmpty for collections.

Can I Implement IsNullOrEmpty for my Generic Collections/Lists?

It's out of C#. Unfortunately, there is only one method which is of a String method String.IsNullOrEmpty() available, framework does not provide us such things.

What is the Solution for this?

A solution is only an Extension Method, we just need to create an Extension Method which will provide the same facility: Here is the extension method:

C#
public static class CollectioncExtensionMethods  
    {  
        public static bool IsNullOrEmpty<T>(this IEnumerable<T> genericEnumerable)  
        {  
            return ((genericEnumerable == null) || (!genericEnumerable.Any()));  
        }  
  
        public static bool IsNullOrEmpty<T>(this ICollection<T> genericCollection)  
        {  
            if (genericCollection == null)  
            {  
                return true;  
            }  
            return genericCollection.Count < 1;  
        }  
    }

Enjoy the benefit of these extension methods. :)

C#
var serverDataList = new List<ServerData>();  

//It will use IsNullOrEmpty<T>(this ICollection<T> gnericCollection)
var result = serverDataList.IsNullOrEmpty();  
 
var serverData = new ServerDataRepository().GetAll();
              
// It will use IsNullOrEmpty<T>(this IEnumerable<T> genericEnumerable)  
var result = serverData.IsNullOrEmpty();

Can You Think What It Will Give When I Call serverDataList.Count and When I Call serverData.Count?

Hint: One will give me O(n) while other O(1), enjoy! :)

If still confused, view this video on .NET collection by legend author, Mr. Shivprasad Koirala.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer
India India
Learning never ends.

Written By
South Africa South Africa
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
D V L23-Aug-15 19:55
professionalD V L23-Aug-15 19:55 
AnswerRe: My vote of 5 Pin
Gaurav Aroraa23-Aug-15 21:56
professionalGaurav Aroraa23-Aug-15 21:56 
QuestionNot really a good idea Pin
William E. Kempf13-Aug-15 6:01
William E. Kempf13-Aug-15 6:01 
AnswerRe: Not really a good idea Pin
mtiede13-Aug-15 10:50
mtiede13-Aug-15 10:50 
GeneralRe: Not really a good idea Pin
codefabricator18-Aug-15 5:55
codefabricator18-Aug-15 5:55 
QuestionNice trick Pin
DotNetForAll13-Aug-15 3:57
DotNetForAll13-Aug-15 3:57 
AnswerRe: Nice trick Pin
Gaurav Aroraa13-Aug-15 4:00
professionalGaurav Aroraa13-Aug-15 4:00 
QuestionGreat Pin
irneb13-Aug-15 2:13
irneb13-Aug-15 2:13 
AnswerRe: Great Pin
Gaurav Aroraa13-Aug-15 3:53
professionalGaurav Aroraa13-Aug-15 3:53 
GeneralRe: Great Pin
irneb13-Aug-15 19:59
irneb13-Aug-15 19:59 
GeneralRe: Great Pin
Gaurav Aroraa13-Aug-15 20:11
professionalGaurav Aroraa13-Aug-15 20:11 
GeneralRe: Great Pin
irneb14-Aug-15 22:55
irneb14-Aug-15 22:55 
Seems I've made a "stupid" error Sigh | :sigh: ... trying to consolidate the print into both Console output as well as CSV in one function I've copy-pasted code and forgot to change the arguments.

Anyhow, did a revamp on the benchmarking test - so it's more of a general purpose test:
C#
namespace Benchmarking
{
    public class BenchmarkTest
    {
        #region Type Declarations

        public static CultureInfo DefaultCulture;

        static BenchmarkTest ()
        {
            DefaultCulture = new CultureInfo ("en-US");
        }

        public static readonly BenchmarkTest Default = new BenchmarkTest();

        public struct Result : IComparable<Result>
        {
            public string Name = string.Empty;
            public long Iterations = -1L;
            public double Seconds = -1d;

            public Result(string name, long iterations, double seconds)
            {
                this.Name = name;
                this.Iterations = iterations;
                this.Seconds = seconds;
                this.singleSeconds = -1d;
            }

            public Result(string name, long iterations, TimeSpan time)
                :this(name, iterations, time.TotalSeconds) {}

            private double singleSeconds = -1d;

            public double SingleIterationSeconds { 
                get { 
                    if (singleSeconds < 0d) {
                        singleSeconds = Seconds / Iterations;
                    }
                    return singleSeconds;
                }
            }

            #region IComparable implementation

            public int CompareTo (Result other)
            {
                return this.SingleIterationSeconds.CompareTo (other.SingleIterationSeconds);
            }

            #endregion
        }

        public enum PrintType { ProgressOnly, RunningResults, None };

        #endregion

        #region Constructors

        public BenchmarkTest(CultureInfo culture,  bool writeToConsole, bool writeToDebug, StreamWriter logStream)
        {
            this.Culture = culture;
            this.WriteToConsole = writeToConsole;
            this.WriteToDebug = writeToDebug;
            this.stream = logStream;
            this.results = new List<Result> ();
        }

        public BenchmarkTest(bool writeToConsole, bool writeToDebug, StreamWriter logStream)
            : this(DefaultCulture, writeToConsole, writeToDebug, logStream)
        {}

        public BenchmarkTest(bool writeToConsole, StreamWriter logStream)
            : this(writeToConsole, false, logStream)
        {}

        public BenchmarkTest(StreamWriter logStream) : this(false, logStream) {}

        public BenchmarkTest(bool writeToConsole, bool writeToDebug)
            : this(writeToConsole, writeToDebug, null)
        {}

        public BenchmarkTest() : this(true, false) {}

        #endregion

        #region Settings

        public CultureInfo Culture;

        public bool WriteToConsole;

        public bool WriteToDebug;

        StreamWriter stream;
        public Stream LogStream {
            set {
                stream = (value == null) ? null : new StreamWriter (value);
            }
        }

        public bool WriteToStream { get { return (stream != null); } }

        public PrintType PrintRunningResults = PrintType.ProgressOnly;

        #endregion

        #region Output

        bool started = false;

        void Print (string name, long iterations, TimeSpan time)
        {
            if (!started) {
                PrintHeader ();
            }
            switch (PrintRunningResults) {
            case PrintType.ProgressOnly:
                if (WriteToConsole) {
                    Console.WriteLine (name);
                }
                if (WriteToDebug) {
                    Debug.WriteLine (name);
                }
                break;
            case PrintType.RunningResults:
                var s = string.Format (Culture, "{0,-30}{1,15}{2,20:F9}", name, iterations, time.TotalSeconds);
                if (WriteToConsole) {
                    Console.WriteLine (s);
                }
                if (WriteToDebug) {
                    Debug.WriteLine (s);
                }
                if (WriteToStream) {
                    s = string.Format (Culture, "\"{0}\",{1},{2:R}", name.Replace (',', '.').Replace('\"', '\''),
                        iterations, time.TotalSeconds);
                    stream.WriteLine (s);
                }
                break;
            }
        }

        void PrintHeader ()
        {
            if (PrintRunningResults == PrintType.RunningResults) {
                var s = string.Format (Culture, "{0,-30}{1,15}{2,20}", "Name", "Iterations", "Seconds");
                var bar = new String ('=', 30 + 15 + 20);
                if (WriteToConsole) {
                    Console.WriteLine (s);
                    Console.WriteLine (bar);
                }
                if (WriteToDebug) {
                    Debug.WriteLine (s);
                    Debug.WriteLine (bar);
                }
                if (WriteToStream) {
                    s = string.Format (Culture, "\"{0}\",\"{1}\",\"{2}\"", "Name", "Iterations", "Seconds");
                    stream.WriteLine (s);
                }
            }
            started = true;
        }

        public void Print()
        {
            if (results.Count < 1) {
                return;
            }
            var s = string.Format (Culture, "{0,-30}{1,15}{2,20}{3,20}", "Name", "Iterations", "Seconds", "Relative");
            var bar = new String ('=', 30 + 15 + 20 + 20);
            if (WriteToConsole) {
                Console.WriteLine (s);
                Console.WriteLine (bar);
            }
            if (WriteToDebug) {
                Debug.WriteLine (s);
                Debug.WriteLine (bar);
            }
            if (WriteToStream) {
                s = string.Format (Culture, "\"{0}\",\"{1}\",\"{2}\",\"{3}\"", "Name", "Iterations", "Seconds", "Relative");
                stream.WriteLine (s);
            }
            Result fastest = Results[0];
            foreach (var result in results) {
                s = string.Format (Culture, "{0,-30}{1,15}{2,20:F9}{3,20:F9}", result.Name, result.Iterations, 
                    result.Seconds, result.SingleIterationSeconds / fastest.SingleIterationSeconds);
                if (WriteToConsole) {
                    Console.WriteLine (s);
                }
                if (WriteToDebug) {
                    Debug.WriteLine (s);
                }
                if (WriteToStream) {
                    s = string.Format (Culture, "\"{0}\",{1},{2:R},{3:R}", result.Name, result.Iterations, 
                        result.Seconds, result.SingleIterationSeconds / fastest.SingleIterationSeconds);
                    stream.WriteLine (s);
                }
            }
        }

        #endregion

        #region Testing

        Stopwatch sw = new Stopwatch ();

        protected List<Result> results;

        public TimeSpan Run (string name, Action act, long iterations = 1)
        {
            if (iterations < 1) {
                throw new ArgumentOutOfRangeException ("iterations", "must be a positive integer");
            }
            act ();
            act ();
            GC.Collect ();
            GC.WaitForPendingFinalizers ();
            act ();
            sw.Restart ();
            for (long i = 0; i < iterations; i++) {
                act ();
            }
            sw.Stop ();
            Print (name, iterations, sw.Elapsed);
            var result = new Result (name, iterations, sw.Elapsed);
            sorted = false;
            results.Add (result);
            return sw.Elapsed;
        }

        public TimeSpan Run (Action act, long iterations = 1)
        {
            return Run (act.GetMethodInfo ().Name, act, iterations);
        }

        public TimeSpan RunAuto (string name, Action act, double seconds = 1.0d)
        {
            if (seconds < 0.0) {
                throw new ArgumentOutOfRangeException ("seconds", "cannot be negative");
            }
            act ();
            act ();
            GC.Collect ();
            GC.WaitForPendingFinalizers ();
            act ();
            long iterations = 0;

            sw.Stop ();
            sw.Reset ();
            while (sw.Elapsed.TotalSeconds < seconds) {
                iterations = (iterations < 1) ? 1 : iterations * 2;
                sw.Restart ();
                for (long i = 0; i < iterations; i++) {
                    act ();
                }
                sw.Stop ();
            }
            Print (name, iterations, sw.Elapsed);
            var result = new Result (name, iterations, sw.Elapsed);
            sorted = false;
            results.Add (result);
            return sw.Elapsed;
        }

        public TimeSpan RunAuto (Action act, double seconds = 1.0d)
        {
            return RunAuto (act.GetMethodInfo ().Name, act, seconds);
        }

        #endregion

        #region Results

        bool sorted = false;

        public IList<Result> Results {
            get {
                if (!sorted) {
                    results.Sort ();
                    sorted = true;
                }
                return results;
            }
        }

        public void Clear()
        {
            results.Clear ();
            sorted = false;
            started = false;
        }

        #endregion
    }
}

Then the testing function using the same class as my previous post:
C#
static void Main(string[] args)
{
    using (StreamWriter f = new StreamWriter(@"Results.CSV", false, Encoding.UTF8)) {
        var b = new Benchmarking.BenchmarkTest (true, f);
        foreach (var act in new Action[] {YieldIntAny, EnumIntAny, EnumIntNullAny, ArrayIntAny,
        ArrayIntLength, ArrayIntNullAny, ArrayIntNullLength, ColIntAny, ColIntCount,
        ColIntNullAny, ColIntNullCount, ColEx, ColEnEx, ArEnEx, ArrayEx, EnumEx}) {
            b.RunAuto (act);
        }
        b.Print ();
    }
    Console.ReadLine ();
}

A bit more useful results:
Name                               Iterations             Seconds            Relative

=====================================================================================
ArrayEx                             536870912         1.593437600         1.000000000
ArrayIntNullLength                  536870912         1.601223200         1.004886040
ArrayIntLength                      536870912         1.607353500         1.008733257
ArrayIntNullAny                     268435456         1.087160600         1.364547441
ColIntNullCount                     268435456         1.150170300         1.443633940
ColIntNullAny                       268435456         1.165076300         1.462343176
EnumIntNullAny                      268435456         1.169268900         1.467605509
ColIntCount                         134217728         1.046758100         2.627672649
ColEx                               134217728         1.046950500         2.628155630
ColIntAny                           134217728         1.054542500         2.647213797
ArEnEx                              134217728         1.449512200         3.638704647
ArrayIntAny                         134217728         1.459083800         3.662732196
EnumEx                              134217728         1.484445900         3.726398574
EnumIntAny                          134217728         1.518965900         3.813053991
ColEnEx                             134217728         1.529009200         3.838265647
YieldIntAny                          33554432         1.022207800        10.264176520 

Seems forcing the Any test on collections is pretty similar to using its Count property.
AnswerRe: Great Pin
Gaurav Aroraa15-Aug-15 22:49
professionalGaurav Aroraa15-Aug-15 22:49 
GeneralRe: Great Pin
irneb16-Aug-15 23:46
irneb16-Aug-15 23:46 
AnswerRe: Great Pin
Gaurav Aroraa17-Aug-15 1:18
professionalGaurav Aroraa17-Aug-15 1:18 
GeneralRe: Great Pin
irneb17-Aug-15 4:48
irneb17-Aug-15 4:48 
AnswerRe: Great Pin
Gaurav Aroraa17-Aug-15 22:37
professionalGaurav Aroraa17-Aug-15 22:37 
GeneralRe: Great Pin
Gaurav Aroraa24-Aug-15 5:29
professionalGaurav Aroraa24-Aug-15 5:29 
GeneralMy vote 5 Pin
Shuby Arora12-Aug-15 10:56
Shuby Arora12-Aug-15 10:56 
GeneralRe: My vote 5 Pin
Gaurav Aroraa13-Aug-15 3:53
professionalGaurav Aroraa13-Aug-15 3:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.