Array Class


Declaring an array with brackets is a C# notation of using the Array class. Using the C# syntax behind the scenes creates a new class that derives from the abstract base class Array. It is possible, in this way, to use methods and properties that are defined with the Array class with every C# array. For example, you’ve already used the Length property or iterated through the array by using the foreach statement. By doing this, you are using the GetEnumerator() method of the Array class.

Properties

The Array class contains the following properties that you can use with every array instance. There are some more properties available that will be discussed later in this chapter.

Open table as spreadsheet

Property

Description

Length

The Length property returns the number of elements inside the array. If the array is a multidimensional array, you get the number of elements of all ranks. If you need to know the number of elements within a dimension, you can use the GetLength() method instead.

LongLength

The Length property returns a int value, the LongLength property returns the length in a long value. If the array contains more elements than fit into a 32-bit int value, you need to use the LongLength property to get the number of elements.

Rank

With the Rank property you get the number of dimensions of the array.

Creating Arrays

The Array class is abstract, so you cannot create an array by using a constructor. However, instead of using the C# syntax to create array instances, it is also possible to create arrays by using the static CreateInstance() method. This is extremely useful if you don’t know the type of the elements in advance, as the type can be passed to the CreateInstance() method as a Type object.

The following example shows how to create an array of type int with a size of 5. The first argument of the CreateInstance() method requires the type of the elements, and the second argument defines the size. You can set values with the SetValue() method, and read values with the GetValue() method.

  Array intArray1 = Array.CreateInstance(typeof(int), 5); for (int i = 0; i < 5; i++) {    intArray1.SetValue(33, i); } for (int i = 0; i < 5; i++) {    Console.WriteLine(intArray1.GetValue(i)); } 

You can also cast the created array to an array declared as int[]:

  int[] intArray2 = (int[])intArray1; 

The CreateInstance() method has many overloads to create multidimensional arrays and also to create arrays that are not 0-based. The following example creates a 2-dimensional array with 2 × 3 elements. The first dimension is 1-based; the second dimension 10-based.

  int[] lengths = { 2, 3 }; int[] lowerBounds = { 1, 10 }; Array racers = Array.CreateInstance(typeof(Person), lengths, lowerBounds); 

Setting the elements of the array, the SetValue() method accepts indices for every dimension:

  racers.SetValue(new Person("Alain", "Prost"), 1, 10); racers.SetValue(new Person("Emerson", "Fittipaldi"), 1, 11); racers.SetValue(new Person("Ayrton", "Senna"), 1, 12); racers.SetValue(new Person("Ralf", "Schumacher"), 2, 10); racers.SetValue(new Person("Fernando", "Alonso"), 2, 11); racers.SetValue(new Person("Jenson", "Button"), 2, 12); 

Although the array is not 0-based you can assign it to a variable with the normal C# notation. You just have to pay attention to not crossing the boundaries.

  Person[,] racers2 = (Person[,])racers; Person first = racers2[1, 10]; Person last = racers2[2, 12]; 

Copying Arrays

Because arrays are reference types, assigning an array variable to another one you just have two variables referencing the same array. For copying arrays, the array implements the interface ICloneable. The Clone() method that is defined with this interface creates a shallow copy of the array.

If the elements of the array are value types, all values are copied, as you can see in Figure 5-5.

  int[] intArray1 = {1, 2}; int[] intArray2 = (int[])intArray1.Clone(); 

image from book
Figure 5-5

If the array contains reference types, the elements are not copied, just the references. Figure 5-6 shows the variables beatles and beatlesClone where beatlesClone is created by calling the Clone() method from beatles. The Person objects that are referenced are the same with beatles and beatlesClone.If you change a property of an element of beatlesClone, you change the same object of beatles.

  Person[] beatles = {                         new Person("John", "Lennon"),                         new Person("Paul", "McCartney")                       }; Person[] beatlesClone = (Person[])beatles.Clone(); 

image from book
Figure 5-6

Instead of using the Clone() method, you can also use the Array.Copy() method that creates a shallow copy as well. But there’s one important difference with Clone and Copy: Clone creates a new array, with Copy you have to pass an existing array with the same rank and enough elements.

Tip 

If you need a deep copy of an array containing reference types, you have to iterate the array and create new objects.

Sorting

The Array class implements a bubble-sort for sorting the elements in the array. The Sort() method requires the interface IComparable to be implemented by the elements in the array. Simple types such as System.String and System.Int32 implement IComparable, so you can sort elements containing these types.

With the sample program, the array name contains elements of type string, and this array can be sorted.

  string[] names = {                    "Christina Aguillera",                    "Shakira",                    "Beyonce",                    "Gwen Stefani"                  }; Array.Sort(names); foreach (string name in names) {    Console.WriteLine(name); } 

The output of the application shows the sorted result of the array:

 Beyonce Christina Aguillera Gwen Stefani Shakira

If you are using custom classes with the array, you must implement the interface IComparable. This interface defines just one method CompareTo() that must return 0 if the objects to compare are equal, a value smaller than 0 if the instance should go before the object from the parameter, and a value larger than 0 if the instance should go after the object from the parameter.

Change the Person class to implement the interface IComparable. The comparison is done on the value of the lastname. As the lastname is of type string, and the String class already implements the ICompareable interface, with the implementation you can rely on the CompareTo() method of the String class:

       public class Person : IComparable      {         public int CompareTo(object obj)         {            Person other = obj as Person;            return this.lastname.CompareTo(other.lastname);         } //... 

Now it is possible to sort an array of Person objects by the last name:

  Person[] persons = {    new Person("Emerson", "Fittipaldi"),    new Person("Niki", "Lauda"),    new Person("Ayrton", "Senna"),    new Person("Michael", "Schumacher") }; Array.Sort(persons); foreach (Person p in persons) {    Console.WriteLine(p); } 

Using the sort of the Person class, the output returns the names sorted by the last name:

 Emerson Fittipaldi Niki Lauda Michael Schumacher Ayrton Senna

If the Person object should be sorted differently, or if you don’t have the option to change the class that is used as an element in the array, you can implement the interface IComparer. This interface defines the method Compare(). The interface IComparable must be implemented by the class that should be compared. The IComparer interface is independent of the class to compare. That’s why the Compare() method defines two arguments that should be compared. The return value is similar to the CompareTo() method of the IComparable interface.

The class PersonComparer implements the IComparer interface to sort Person objects either by firstname or by lastname. The enumeration PersonCompareType defines the different sorting options that are available with the PersonComparer: Firstname and Lastname. How the compare should happen is defined with the constructor of the class PersonComparer where a PersonCompareType value is set. The Compare() method is implemented with a switch statement to compare either by lastname or by firstname.

  public class PersonComparer : IComparer {    public enum PersonCompareType    {       Firstname,       Lastname    }    private PersonCompareType compareType;    public PersonComparer(PersonCompareType compareType)    {       this.compareType = compareType;    }    public int Compare(object x, object y)    {       Person p1 = x as Person;       Person p2 = y as Person;       switch (compareType)       {          case PersonCompareType.Firstname:             return p1.Firstname.CompareTo(p2.Firstname);          case PersonCompareType.Lastname:             return p1.Lastname.CompareTo(p2.Lastname);          default:             throw new ArgumentException("unexpected compare type");       }    } } 

Now you can pass a PersonComparer object to the second argument of the Array.Sort() method. Here the persons are sorted by first name:

  Array.Sort(persons,    new PersonComparer(PersonComparer.PersonCompareType.Firstname)); foreach (Person p in persons) {    Console.WriteLine(p); } 

The persons array is now sorted by the first name:

 Ayrton Senna Emerson Fittipaldi Michael Schumacher Niki Lauda

Tip 

The Array class also offers Sort methods that require a delegate as an argument. In Chapter 7, “Delegates and Events,” you can read all the information on how to use delegates.




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net