Click here to Skip to main content
Click here to Skip to main content

Effective C# - Part I

, 5 Apr 2005
Rate this:
Please Sign up or sign in to vote.
Make your C# code efficient.

Introduction

The following set of effective C# articles contains various ways to improve your C# code.

The Code Project, as a large developers' community, is the right place to discuss ways to write more efficient code. This is a knowledge infrastructure that allows us to become better developers by writing better code. I hope you post new messages and new ways to write effective C# code.

Background

This article is built from separate items. Each item deals with a certain aspect of efficient C# code (Performance, Usage, Garbage collector etc.) followed by code snippets.

Contents

Item 1 - Prefer the Length property when checking string size [ Performance]

String comparison involves unnecessary overhead. If all you need is to check whether the string is empty, use the Length property.

Code snippets:

//NO
if ( str != “”)//comparison of two strings {...}
//YES
if ( str.Length > 0) {...}

Item 2 - Prefer StringBuilder instead of string concatenation. [Performance ]

C# string is immutable, i.e., cannot be altered. When you alter a string, you are actually creating a new string causing the following:

  • The code uses more memory than necessary.
  • Creates more work for the garbage collector.
  • Makes the code execution run slower.

Therefore, you should prefer using StringBuilder (Append method).

Code snippets:

//NO
String strConcat;
ArrayList arrayOfStrings = new ArrayList();
arrayOfStrings.Add("a"); 
arrayOfStrings.Add("b");
foreach (string s in stringContainer) {
  strConcat += s; 
}

//YES
StringBuilder sbConcat = new StringBuilder ();
foreach (string s in arrayOfStrings ) { 
  sbConcat.append(s);
}

Item 3 - Avoid Boxing and UnBoxing as much as possible. [Performance]

Boxing a value of a value-type consists of two operations:

  • Allocating an object instance.
  • Copying the value-type value into that instance.

Given the above, you should avoid Boxing as much as you can. If you intend to work with ArrayList, for example, do not declare your data type as struct (Value type) because ArrayList works with Object (Reference type) and every time you add an instance of the struct or run over the container, in a loop, a Boxing process will occur.

The following happens when you copy one of the collection items value into the struct:

  • Casting.
  • Copy the value.

Note: Collections expect object type.

Code snippets:

//NO
struct st { public Int i; }
Arraylist arr = new ArrayList();
for (int i=0 ; i< count; i++) { 
  st s;
  s.i = 4; 
  arr.item.add(st) ; //<- Boxing (Allocating an object instance
                     // + copying the value-type value into that instance)
}
st obj = (st ) arr[0]; //<- Unboxing (casting and copy)

//YES
//Decalre the data type as class.
Class st { public Int i; }

Item4 - Prefer String.Equal method instead of == operator. [Performance]

Using the string.Equals method is much faster when the strings are matched. So if you are very keen and need special type of performance and expect that most of the strings will be the same, use the Equal method.

Note: The differences in performance are negligible and effects only numerous operations.

Code snippets:

string s1= "code";
string s2 = "code1";
//No:
if(s1 == s2){...}
//Yes:
if(s1.Equals(s2)){...}

Item5 - Use Native Image Generator (nGen.exe) in case of long and heavy initialization. [Performance]

The .NET Framework runs C# assemblies using the JIT compiler. Each code that is executed for the first time is being compiled. In case of heavy and long initialization in your assembly, you might want to use the nGen .NET tool.

"The nGen creates a native image from a managed assembly and installs it into the native image cache on the local computer.

Once you create a native image for an assembly, the runtime automatically uses that native image each time it runs the assembly. You do not have to perform any additional procedures to cause the runtime to use a native image. Running Ngen.exe on an assembly allows the assembly to load and execute faster, because it restores code and data structures from the native image cache rather than generating them dynamically." (MSDN 2005)

You do not have to lose the advantage of JIT compilation, because you can call the nGen command on the installation machine through your project setup, using:

ngen [options] [assemblyName |assemblyPath ]

Item6 - Prefer 'for' over 'foreach'. [Performance]

'foreach' and 'for' statements serve the same goal - run in loop over block of statements.

The main differences in using the foreach statement are that you do not need to deal with increments and with the end of the loop expression. Moreover, the foreach statement is designed to traverse through the entire collection. One can say that foreach is a private case of for.

In the code snippets below, we can see that both loop blocks produce the same results, only under the hood the foreach hurts the performance. More variables are involved and additional heavy array copy.

The foreach is far more handier to use especially for collections but if your code runs over large collections, prefer using 'for'.

Code snippets:

//foreach
int[] arrayOfInts= new int[5];
int sum= 0; 
foreach(int i arrayOfInts) {
  sum+= i; 
}

//for
int[] arrayOfInts= new int[1]; 
int sum= 0;
for(int i = 0; i < arrayOfInts.Length; i++) {
  sum+= arrayOfInts[i]; 
}

Item7 - Prefer the ‘as’ operator instead of direct type casting. [Usage]

The 'as' operator does not throw an exception. In case of bad cast, the return value is null.

Code snippets:

//NO
object o = 1.3; 
try
{
  string str = (string)o; 
} 
catch(InvalidCastException ex){...}

//YES
string str = o as string;
if(null != str){...}

Item8 - Use the 'checked' keyword to avoid overflow. [Usage]

Code snippets:

//NO
short shortNum;
int i = 32768;
shortNum = (short) i; 
// problem after statment excution
// the shortNum variable has an uninitialized value,

//YES
try {
  shortNum = checked((short)i); // solution 
}
catch(OverflowException efx) {}

Item9 - Use the 'is' operator instead of casting. [Usage]

Code snippets:

public class Preson{int nAge;}

//No:
static void main(object o){
  try {
    (Person)o.nAge = 45;
  }
  catch(InvalidCastException ex){...}
}

//Yes:
static void func(object o)
{
  if ( true == (o is Person) )
  {
    (Person)o.nAge = 45;
  }
}

Item10 - Use Explicit interface to 'hide' the implementation of an interface [Usage]

Implementing an interface explicitly 'hides' the interface methods. Visual Studio does not display the interface methods in the intellisense.

Code snippets:

//interface definition
Public interface IChild{
  bool IsHuman();
  void lie();
}

//class definition
Pubic Pinocchio: IChild {
  IChild.IsHuman() //explicit interface implementation
  {
  }
  public void Lie(); //regular interface implementation
}

//using the object
static void main()
{
  // Visual studio will not display
  // the isHuman mwthod in the intellisence.
  Pinocchio o = new Pinocchio();
  ((IChild) o).IsHuman(); // using the IsHuman method explicitly.
  o.Lie();
}

Item11 - Use @ to ease the work with literal paths. [Usage]

Code snippets:

//Old way
String sFilePath = “c:\\a\\b\\c.txt”;

//The C# way
String sFilePath = @”c:\a\b\c.txt”;

Item12 - Make your API assembly CLS Compliant. [Usage]

The CLS-Compliant attribute cause the compiler to check whether your public exposed types in the assembly are CLS-Compliant.

Prefer to define the attribute for the entire assembly, especially for API. The incentive to create a CLS compliant assembly is that any assembly written in one of the .NET aware languages can use your assembly more efficiently because there is no data types interoperability.

Code snippets:

using System; 
[assembly:CLSCompliant(true)]

Item13 - Define destructor and implement IDisposable interface for classes that use native resource directly. [Garbage Collection]

You should define a destructor whenever you use native code in your assembly, i.e., use types that are not managed by the garbage collector. The compiler changes the destructor method to Finalize method (can be seen in the MSIL using the ILDasm.exe).

The Garbage collector marks a class with destructor as Finalized and calls the Finalize method while destructing the object. This behavior guarantees that your release of resources in the destructor will occur.

But, what if you want to release the resources immediately? For this purpose, you should implement the IDisposable interface and call the Dispose method when you want to release the object.

Note 1: Do not use destructor if your class does not use native / unmanaged resources. If you do so, you create unnecessary work for the garbage collector.

Note 2: If you implement the IDisposable and a destructor, you should call the Dispose method from the destructor to force the object to release resources immediately.

Code snippets:

~my class {
  if ( true == b) { 
  }
} 

//The MSIL code:
protected override void Finalize() {
  try { 
    if ( true == b) { 
    }
  }finally { base.Finalize();} 
}

Item14 - Avoid the use of GC.Collect. [Garbage Collection]

The GC.Collect method forces garbage collection of all generations.

The performance is hurt during the call to GC.Collect, the application execution is paused. Moreover, the method might cause the promotion of short lived objects to a higher generation, i.e., those object live longer than it should in the first place.

If you must use it in order to reclaim the maximum amount of available memory, use the method only on generation 0.

Code snippets:

//No:
GO.Collect();
//Yes:
GC.Collect(0);

Item15 - Use StructLayout attribute for classes and structs when using COM Interop. [COM Interop]

The attributes cause the compiler to pack the structure in sequential memory so that it can be sent to unmanaged code correctly (unmanaged code that expects a specific layout).

Code snippets:

using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)] 
public struct st{
  int i;
  float f;
}

What next?

The part II article, will deal with COM Interop in general, and events between managed and unmanaged code in particular.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

No Biography provided

Comments and Discussions

 
GeneralMy vote of 1 PinmemberJalalAldeen16-Feb-10 22:41 
GeneralRe: My vote of 1 PinmemberMarcus Kramer3-Dec-10 13:36 
GeneralFOREACH vs FOR, tested again. FOR wins. Pinmemberbluedog says3-Jun-09 11:32 
While reading all the conflicting reports, I wrote my own little sample, posted below. Here are the results:
 
Object Test Results
 
FOR loop time on ArrayList with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 88.6
 
FOREACH loop time on ArrayList with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 115.9
 
FOR loop time on generic collection with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 84.4
 
FOREACH loop time on generic collection with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 87.1
 
FOR loop time on array with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 48.1
 
FOREACH loop time on array with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 49.8
 
Int Test Results
 
FOR loop time on ArrayList with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 65.1
 
FOREACH loop time on ArrayList with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 134
 
FOR loop time on generic collection with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 51.6
 
FOREACH loop time on generic collection with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 72.2
 
FOR loop time on array with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 17.5
 
FOREACH loop time on array with 2147483 items looped 10 times:
Average Elapsed Milliseconds: 21.7
 
This tests ArrayLists, Generic collections, and arrays holding the same type of information with the same lengths. The for/foreach loops do nothing more then set a number. Personally I wish the results were the opposite as foreach is less to type then for (int i = i < ? ; i++)
 
You can run this sample and it will loop millions and millions of objects/ints and average them to produce a viable result. I ran it about 10 times now illiterating through over 100 million items with the same results each time.
 
By default the sample will pause 5 seconds in between runs. You can optionally output the results to a file as well. If you find any issues please post them. FYI this sample was ran on a 1.6ghz x 2 Vista laptop with 2gb of ram if you want to compare results.
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Collections;
using System.Threading;
using System.IO;
 
namespace FOREACHVSFOR
{
    /// <summary>
    /// Checks FOREACH VS FOR.
    /// Code can be ran to check multiple times and take the average or to take the total.
    /// </summary>
    class Program
    {
        #region Array/Collection
        static ArrayList ari1 = null;
        static ArrayList ari2 = null;
        static List<int> ari3 = null;
        static List<int> ari4 = null;
        static int[] ari5 = null;
        static int[] ari6 = null;
 
        static ArrayList arl1 = null;
        static ArrayList arl2 = null;
        static List<BoringObjectClass> arl3 = null;
        static List<BoringObjectClass> arl4 = null;
        static BoringObjectClass[] arl5 = null;
        static BoringObjectClass[] arl6 = null;
        #endregion
 
        #region Times
        static long ar1Time = 0;
        static long ar2Time = 0;
        static long ar3Time = 0;
        static long ar4Time = 0;
        static long ar5Time = 0;
        static long ar6Time = 0;
        #endregion
 
        /// <summary>
        /// Class to test out in collection.
        /// </summary>
        class BoringObjectClass: Object
        {
            /// <summary>
            /// Some int to use.
            /// </summary>
            public int SomeInt = 0;
            public BoringObjectClass(int v)
            {
                SomeInt=v;
            }
        }
        /// <summary>
        /// Set at runtime by user.
        /// </summary>
        static int intsToTest = 0;
 
        /// <summary>
        /// Set at runtime by user.
        /// </summary>
        static int objectsToTest = 0;
 
        /// <summary>
        /// Output results to a log file?
        /// </summary>
        static bool SaveToLog = true;
 
        /// <summary>
        /// Log file name, if you want to log info set SaveToLog to true.
        /// </summary>
        static string LogFileName = "FORVSFOREACH.log";
 
        /// <summary>
        /// Set to true if you want to append the current log file (if any) otherwise we will overwrite.
        /// </summary>
        static bool AppendLog = false;
 
        /// <summary>
        /// Let the thread sleep in between runs.
        /// </summary>
        static int SleepTimeInBetween = 5000;
 
        /// <summary>
        /// Stores results.
        /// </summary>
        static StringBuilder builder;
 
        /// <summary>
        /// Char array to split new lines.
        /// </summary>
        static char[] sp = new char[] { char.Parse("\n") };
 
        /// <summary>
        /// Runs the check on arrays of ints.
        /// </summary>
        static void IntCheck()
        {
            Stopwatch sp = new Stopwatch();
            int fill = 0;
 
            if (ari1 == null || ari1.Count != intsToTest)
            {
                ari1 = null;
                ari1 = new ArrayList(intsToTest);
            }
            if (ari2 == null || ari2.Count != intsToTest)
            {
                ari2 = null;
                ari2 = new ArrayList(intsToTest);
            }
            if (ari3 == null || ari3.Count != intsToTest)
            {
                ari3 = null;
                ari3 = new List<int>(intsToTest);
            }
            if (ari4 == null || ari4.Count != intsToTest)
            {
                ari4 = null;
                ari4 = new List<int>(intsToTest);
            }
            if (ari5 == null || ari5.Length != intsToTest)
            {
                ari5 = null;
                ari5 = new int[intsToTest];
            }
            if (ari6 == null || ari6.Length != intsToTest)
            {
                ari6 = null;
                ari6 = new int[intsToTest];
            }
 
            while (fill < intsToTest)
            {
                ari1.Add(fill);
                ari2.Add(fill);
                ari3.Add(fill);
                ari4.Add(fill);
                ari5[fill] = fill;
                ari6[fill] = fill;
 
                fill++;
            }
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            for (int i = 0; i < ari1.Count; i++)
                fill = (int) ari1[i];
            sp.Stop();
            ar1Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            foreach (int i in ari2)
                fill = (int) ari2[i];
            sp.Stop();
            ar2Time+= sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            for (int i = 0; i < ari3.Count; i++)
                fill = ari3[i];
            sp.Stop();
            ar3Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            foreach (int i in ari4)
                fill = ari4[i];
            sp.Stop();
            ar4Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            for (int i = 0; i < ari5.Length; i++)
                fill = ari5[i];
            sp.Stop();
            ar5Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            foreach (int i in ari6)
                fill = ari6[i];
            sp.Stop();
            ar6Time += sp.ElapsedMilliseconds;
            fill = 0;
        }
 
        /// <summary>
        /// Runs the check on arrays of objects.
        /// </summary>
        static void ObjectCheck()
        {
            Stopwatch sp = new Stopwatch();
            int fill = 0;
 
            if (arl1 == null || arl1.Count != objectsToTest)
            {
                arl1 = null;
                arl1 = new ArrayList(objectsToTest);
            }
            if (arl2 == null || arl2.Count != objectsToTest)
            {
                arl2 = null;
                arl2 = new ArrayList(objectsToTest);
            }
            if (arl3 == null || arl3.Count != objectsToTest)
            {
                arl3 = null;
                arl3 = new List<BoringObjectClass>(objectsToTest);
            }
            if (arl4 == null || arl4.Count != objectsToTest)
            {
                arl4 = null;
                arl4 = new List<BoringObjectClass>(objectsToTest);
            }
            if (arl5 == null || arl5.Length != objectsToTest)
            {
                arl5 = null;
                arl5 = new BoringObjectClass[objectsToTest];
            }
            if (arl6 == null || arl6.Length != objectsToTest)
            {
                arl6 = null;
                arl6 = new BoringObjectClass[objectsToTest];
            }
 
            while (fill < objectsToTest)
            {
                arl1.Add(new BoringObjectClass(fill));
                arl2.Add(new BoringObjectClass(fill));
                arl3.Add(new BoringObjectClass(fill));
                arl4.Add(new BoringObjectClass(fill));
                arl5[fill] = new BoringObjectClass(fill);
                arl6[fill] = new BoringObjectClass(fill);
 
                fill++;
            }
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            for (int i = 0; i < arl1.Count; i++)
                fill = (arl1[i] as BoringObjectClass).SomeInt;
            sp.Stop();
            ar1Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            foreach (BoringObjectClass i in arl2)
                fill = i.SomeInt;
            sp.Stop();
            ar2Time+= sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            for (int i = 0; i < arl3.Count; i++)
                fill = arl3[i].SomeInt;
            sp.Stop();
            ar3Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            foreach (BoringObjectClass i in arl4)
                fill = i.SomeInt;
            sp.Stop();
            ar4Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            for (int i = 0; i < arl5.Length; i++)
                fill = arl5[i].SomeInt;
            sp.Stop();
            ar5Time += sp.ElapsedMilliseconds;
 
            fill = 0;
            sp.Reset();
            Thread.Sleep(SleepTimeInBetween);
            sp.Start();
            foreach (BoringObjectClass i in arl6)
                fill = i.SomeInt;
            sp.Stop();
            ar6Time += sp.ElapsedMilliseconds;
            fill = 0;
        }
 
        /// <summary>
        /// Starts the check on arrays of ints.
        /// </summary>
        static void BeginIntCheck()
        {
            int illiterations = 0;
 
            while (true)
            {
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine("Integer Test.");
                Console.WriteLine("Press: Enter to run [n] times. R to average [n] times. A to add [n] times. Escape to go back.");
               
                ar1Time = 0;
                ar2Time = 0;
                ar3Time = 0;
                ar4Time = 0;
                ar5Time = 0;
                ar6Time = 0;
                builder = new StringBuilder();
 
                switch (Console.ReadKey().Key)
                {
                    case ConsoleKey.Enter:
                        intsToTest = GetCount();
                        Console.WriteLine();
                        Console.WriteLine("Running... This may take a few minutes.");
 
                        IntCheck();
 
                        builder.AppendLine("Int Test Results");
                        builder.AppendLine("FOR loop time on ArrayList with " + intsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar1Time);
                        builder.AppendLine("FOREACH loop time on ArrayList with " + intsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar2Time);
                        builder.AppendLine("FOR loop time on generic collection with " + intsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar3Time);
                        builder.AppendLine("FOREACH loop time on generic collection with " + intsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar4Time);
                        builder.AppendLine("FOR loop time on array with " + intsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar5Time);
                        builder.AppendLine("FOREACH loop time on array with " + intsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar6Time);
                        LogIt();
 
                        builder.Remove(0, builder.Length);
                        builder = null;
 
                        break;
                    case ConsoleKey.A:
                        intsToTest = GetCount();
                        Console.WriteLine();
                        illiterations = GetIlliterations();
                        Console.WriteLine();
                        Console.WriteLine("Running... This may take a few minutes.");
 
                        for (int i = 0; i < illiterations; i++)
                            IntCheck();
 
                        builder.AppendLine("Int Test Results");
                        builder.AppendLine("FOR loop time on ArrayList with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar1Time);
                        builder.AppendLine("FOREACH loop time on ArrayList with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar2Time);
                        builder.AppendLine("FOR loop time on generic collection with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar3Time);
                        builder.AppendLine("FOREACH loop time on generic collection with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar4Time);
                        builder.AppendLine("FOR loop time on array with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar5Time);
                        builder.AppendLine("FOREACH loop time on array with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar6Time);
                        LogIt();
 
                        builder.Remove(0, builder.Length);
                        builder = null;
 
                        break;
                    case ConsoleKey.R:
                        intsToTest = GetCount();
                        Console.WriteLine();
                        illiterations = GetIlliterations();
                        Console.WriteLine();
                        Console.WriteLine("Running... This may take a few minutes.");
 
                        for (int i = 0; i < illiterations; i++)
                            IntCheck();
 
                        builder.AppendLine("Int Test Results");
                        builder.AppendLine("FOR loop time on ArrayList with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar1Time / (decimal) illiterations ));
                        builder.AppendLine("FOREACH loop time on ArrayList with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar2Time / (decimal) illiterations ));
                        builder.AppendLine("FOR loop time on generic collection with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar3Time / (decimal) illiterations ));
                        builder.AppendLine("FOREACH loop time on generic collection with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar4Time /(decimal) illiterations ));
                        builder.AppendLine("FOR loop time on array with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar5Time / (decimal) illiterations ));
                        builder.AppendLine("FOREACH loop time on array with " + intsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar6Time / (decimal) illiterations ));
                        builder.AppendLine();
                        LogIt();
 
                        builder.Remove(0, builder.Length);
                        builder = null;
 
                        break;
                    case ConsoleKey.Escape:
                        return;
                    default:
                        break;
                }
            }
        }
 
        /// <summary>
        /// Starts the check on arrays of objects.
        /// </summary>
        static void BeginObjCheck()
        {
            int illiterations = 0;
 
            while (true)
            {
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine("Object Test.");
                Console.WriteLine("Press: Enter to run [n] times. R to average [n] times. A to add [n] times. Escape to go back.");
 
                ar1Time = 0;
                ar2Time = 0;
                ar3Time = 0;
                ar4Time = 0;
                ar5Time = 0;
                ar6Time = 0;
                builder = new StringBuilder();
 
                switch (Console.ReadKey().Key)
                {
                    case ConsoleKey.Enter:
                        objectsToTest = GetCount();
                        Console.WriteLine();
                        Console.WriteLine("Running... This may take a few minutes.");
 
                        ObjectCheck();
 
                        builder.AppendLine("Object Test Results");
                        builder.AppendLine("FOR loop time on ArrayList with " + objectsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar1Time);
                        builder.AppendLine("FOREACH loop time on ArrayList with " + objectsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar2Time);
                        builder.AppendLine("FOR loop time on generic collection with " + objectsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar3Time);
                        builder.AppendLine("FOREACH loop time on generic collection with " + objectsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar4Time);
                        builder.AppendLine("FOR loop time on array with " + objectsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar5Time);
                        builder.AppendLine("FOREACH loop time on array with " + objectsToTest + " items:");
                        builder.AppendLine("Elapsed Milliseconds: " + ar6Time);
                        LogIt();
 
                        builder.Remove(0, builder.Length);
                        builder = null;
 
                        break;
                    case ConsoleKey.A:
                        objectsToTest = GetCount();
                        Console.WriteLine();
                        illiterations = GetIlliterations();
                        Console.WriteLine();
                        Console.WriteLine("Running... This may take a few minutes.");
 
                        for (int i = 0; i < illiterations; i++)
                            ObjectCheck();
 
                        builder.AppendLine("Object Test Results");
                        builder.AppendLine("FOR loop time on ArrayList with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar1Time);
                        builder.AppendLine("FOREACH loop time on ArrayList with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar2Time);
                        builder.AppendLine("FOR loop time on generic collection with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar3Time);
                        builder.AppendLine("FOREACH loop time on generic collection with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar4Time);
                        builder.AppendLine("FOR loop time on array with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar5Time);
                        builder.AppendLine("FOREACH loop time on array with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Total Elapsed Milliseconds: " + ar6Time);
                        LogIt();
 
                        builder.Remove(0, builder.Length);
                        builder = null;
 
                        break;
                    case ConsoleKey.R:
                        objectsToTest = GetCount();
                        Console.WriteLine();
                        illiterations = GetIlliterations();
                        Console.WriteLine();
                        Console.WriteLine("Running... This may take a few minutes.");
 
                        for (int i = 0; i < illiterations; i++)
                            ObjectCheck();
 
                        builder.AppendLine("Object Test Results");
                        builder.AppendLine("FOR loop time on ArrayList with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar1Time / (decimal) illiterations ));
                        builder.AppendLine("FOREACH loop time on ArrayList with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar2Time / (decimal) illiterations ));
                        builder.AppendLine("FOR loop time on generic collection with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar3Time / (decimal) illiterations ));
                        builder.AppendLine("FOREACH loop time on generic collection with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar4Time /(decimal) illiterations ));
                        builder.AppendLine("FOR loop time on array with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar5Time / (decimal) illiterations ));
                        builder.AppendLine("FOREACH loop time on array with " + objectsToTest + " items looped " + illiterations + " times:");
                        builder.AppendLine("Average Elapsed Milliseconds: " + ( ar6Time / (decimal) illiterations ));
                        builder.AppendLine();
                        LogIt();
 
                        builder.Remove(0, builder.Length);
                        builder = null;
 
                        break;
                    case ConsoleKey.Escape:
                        return;
                    default:
                        break;
                }
            }
        }
 
        /// <summary>
        /// Gets the count of elements to use for testing. Too high and your memory will pass 1gb.
        /// </summary>
        /// <returns>Int containing count.</returns>
        static int GetCount()
        {
            while (true)
            {
                Console.WriteLine();
                Console.WriteLine("How many elements to check?");
                Console.WriteLine("Enter 0 to use the default of int.MaxValue / 1000.");
 
                int iElements = 0;
                if (int.TryParse(Console.ReadLine(), out iElements))
                {
                    if (iElements > 0)
                        return iElements;
                    else if (iElements == 0)
                        return int.MaxValue / 1000;
                }
            }
        }
 
        /// <summary>
        /// How many times to run the test?
        /// </summary>
        /// <returns>Int holding requested illiterations.</returns>
        static int GetIlliterations()
        {
            while (true)
            {
                Console.WriteLine();
                Console.WriteLine("How many illiterations?");
 
                int iIlliterations = 0;
                if (int.TryParse(Console.ReadLine(), out iIlliterations))
                {
                    if (iIlliterations > 0)
                        return iIlliterations;
                }
            }
        }
 
        /// <summary>
        /// Log to file if SaveToLog is true. Print results out to the console.
        /// </summary>
        static void LogIt()
        {
            if (SaveToLog && builder.Length > 0)
            {
                StreamWriter wrt = null;
 
                try
                {
                    wrt = new StreamWriter(LogFileName, AppendLog);
 
                    foreach (string L in builder.ToString().Split(sp))
                        if (L.Length > 0)
                        {
                            Console.WriteLine(L);
                            wrt.WriteLine(L);
                        }
                }
                finally
                {
                    if (wrt != null)
                    {
                        wrt.Close();
                        wrt = null;
                    }
                }
            }
            else
                foreach (string L in builder.ToString().Split(sp))
                    if (L.Length > 0)
                        Console.WriteLine(L);
        }
 
        /// <summary>
        /// FOREACH VS FOR CHECK
        /// </summary>
        /// <param name="args">Nothing</param>
        static void Main(string[] args)
        {
            Console.WriteLine("FOREACH VS FOR CHECK");
 
            while (true)
            {
                Console.WriteLine();
                Console.WriteLine("Press: O to test with objects. I to test with integers. Escape to exit.");
 
                switch (Console.ReadKey().Key)
                {
                    case ConsoleKey.O:
                        BeginObjCheck();
                        break;
                    case ConsoleKey.I:
                        BeginIntCheck();
                        break;
                    case ConsoleKey.Escape:
                        return;
                }
            }
 
        }
    }
}

Generalthank you Pinmemberjustintimberlake24-Feb-09 22:56 
GeneralMy vote of 1 Pinmemberhassan salman25-Jan-09 2:59 
Generalfor vs foreach Pinmemberwitnes11-Jun-08 2:01 
GeneralRe: for vs foreach Pinmemberxusword2-Apr-09 2:18 
GeneralItem 1 string.IsNullOrEmpty() PinmemberMFC User113-Sep-06 22:04 
Generaluse the count property in loops PinmemberCohen Shwartz Oren8-Feb-06 4:32 
Generalif (true == ...) statements Pinmemberdumky13-Dec-05 8:41 
GeneralRe: if (true == ...) statements PinmemberJun Du8-Mar-06 6:54 
GeneralRe: if (true == ...) statements Pinmemberahz19-Jun-06 8:34 
GeneralItem 4 ... PinsussAnonymous22-Apr-05 11:22 
Generalitems 1 &amp; 4: null checking before string comparison PinmemberJeff Hoover18-Apr-05 4:36 
GeneralItem 3 is just plain wrong! PinmemberexDreamDuck16-Apr-05 8:34 
GeneralRe: Item 3 is just plain wrong! Pinmemberchriswa16-Apr-05 15:01 
GeneralRe: Item 3 is just plain wrong! PinsussAnonymous22-Apr-05 11:15 
QuestionWhy do you test for true? PinsussAnonymous12-Apr-05 20:29 
AnswerRe: Why do you test for true? PinmemberChristian Graus12-Apr-05 20:43 
GeneralRe: Why do you test for true? Pinsussreman12-Apr-05 21:44 
GeneralRe: Why do you test for true? PinmemberFrank Hileman13-Apr-05 3:45 
QuestionFeedback: looking for more of this? PinmemberRoman Antchik12-Apr-05 14:21 
GeneralItem 6 - wrong point of view. PinmemberPeter Ritchie12-Apr-05 9:28 
GeneralRe: Item 6 - wrong point of view. PinmemberSlavaT12-Apr-05 17:59 
GeneralRe: Item 6 - wrong point of view. PinmemberAlan Balkany3-Apr-07 8:50 
GeneralEffectice C# Book PinsussM G Vinod Kumar11-Apr-05 1:23 
GeneralGood performance articles PinmemberCohen Shwartz Oren9-Apr-05 7:28 
GeneralI was going to critisize your tips PinsussEnnis Lynch7-Apr-05 12:01 
GeneralRe: I was going to critisize your tips PinmemberCohen Shwartz Oren7-Apr-05 12:49 
GeneralOn optimization PinmemberJeffrey Sax7-Apr-05 5:31 
GeneralRe: On optimization Pinmemberleppie12-Apr-05 12:12 
QuestionGood reference. what about Enumeration and Indexing? Pinmembermark_he6-Apr-05 22:48 
AnswerRe: Good reference. what about Enumeration and Indexing? PinmemberCohen Shwartz Oren6-Apr-05 23:08 
GeneralRe: Good reference. what about Enumeration and Indexing? Pinmemberchriswa16-Apr-05 15:11 
GeneralFurther optimizing Item #9 PinmemberMarc Scheuner6-Apr-05 22:20 
GeneralSuperficial and incomplete article PinsussAnonymous6-Apr-05 19:29 
GeneralRe: Superficial and incomplete article PinsussAnonymous12-Apr-05 20:31 
GeneralRe: Superficial and incomplete article PinsussAnonymous16-Apr-05 14:33 
GeneralRe: Superficial and incomplete article Pinmemberchriswa16-Apr-05 15:09 
GeneralRe: Superficial and incomplete article Pinmemberabstractsagacity7-Jun-05 11:51 
GeneralItem4 PinmemberGiancarlo Aguilera6-Apr-05 16:48 
GeneralRe: Item4 PinmemberJanSchreuder18-Apr-05 20:46 
GeneralRe: Item4 PinmemberGiancarlo Aguilera19-Apr-05 5:39 
GeneralWrong Title! PinmemberMatt Gerrans6-Apr-05 15:50 
GeneralRe: Wrong Title! PinmemberPeter Ritchie12-Apr-05 8:28 
GeneralItem # 1 - Prefer the Length property when checking string size Pinmembermalharone6-Apr-05 15:17 
GeneralRe: Item # 1 - Prefer the Length property when checking string size Pinmembermalharone6-Apr-05 15:20 
GeneralRe: Item # 1 - Prefer the Length property when checking string size PinsussAnonymous6-Apr-05 19:17 
GeneralRe: Item # 1 - Prefer the Length property when checking string size PinmemberRussKie9-Apr-05 13:22 
GeneralRe: Item # 1 - Prefer the Length property when checking string size PinsussCameron Elliot11-Apr-05 1:40 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150327.1 | Last Updated 5 Apr 2005
Article Copyright 2005 by Cohen Shwartz Oren
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid