MS 70-536.1
Part 1. Developing applications that use types and collections
[edit | edit source]1.1 Manage data in a .NET Framework application by using the .NET Framework 2.0 system types.
[edit | edit source]Data types are separated into value types and reference types. Value types are either stack-allocated or allocated inline in a structure.
Reference types are heap-allocated. Both reference and value types are derived from the ultimate base class System.Object.
In cases where a value type needs to act like an object, a wrapper that makes the value type look like a reference object is allocated on the heap, and the value type's value is copied into it. The wrapper is marked so that the system knows that it contains a value type. This process is known as boxing, and the reverse process is known as unboxing. Boxing and unboxing allow any type to be treated as an object.
In .Net and mono (nearly) everything is a Type. The key to finding out about types is the System.Type class. This class can be used to investigate a type. The quickest way to get hold of a type in c# is to use the typeof operator. This operator returns a System.Type object.
using System; namespace OpenEd.Ms70536.Part1.Section1 { public class TypeQuery { public static void Main () { // Getting an instance of Type in c#. Console.WriteLine (typeof (Type).FullName); // Getting an instance is more complicated using the CTS. Console.WriteLine (Type.GetType ("System.Type").FullName); } } }
1.1.1 Value types
[edit | edit source]We can investigate types using System>Type and some reflection.
using System;
1.1.2 Reference types
[edit | edit source]1.1.3 Attributes
[edit | edit source]1.1.4 Generic types
[edit | edit source]1.1.5 Exception classes
[edit | edit source]See: System.Exception
All exceptions derive from the System.Exception class. This class has three constructors to throw a new exception either the first or second constructor can be used. To throw a nested exception the third constructor is used. Each of the constructors is illustrated below.
using System; public class ThrowSimpleException { public static void Main () { throw new Exception(); } }
using System; public class ThrowExceptionWithMessage { public static void Main () { throw new Exception ("Exception with message was thrown."); } }
using System; public class ThrowNestedException { public static void Main () { Exception innerException = new Exception ("Inner exception message."); throw new Exception ("Outer exception message.", innerException); } }
In practice exceptions that are thrown should derive from System.Exception. It is bad practice to throw System.Exception directly.
1.1.6 Boxing and UnBoxing
[edit | edit source]1.1.7 TypeForwardedToAttribute Class
[edit | edit source]1.2 Manage a group of associated data in a .NET Framework application by using collections.
[edit | edit source]Managing groups of data as a unit where each data item can be accessed is a common operation. The System.Collections namespace provides several different types for managing collections. The collections are related to one another by the fact that they implement IEnumrable and ICollection (Check this).
The three interfaces IList, ICollection and IDictionary are structured in the following way:
ICollection : IEnumerable IList : ICollection, IEnumerable IDictionary : ICollection, IEnumerable |
O-- IEnumerable ^ | O-- ICollection ^ | |--------|--------| | | O-- IDictionary O-- IList |
The main classes of System.Collections are as follows:
ArrayList : IList BitArray : ICollection HashTable : IDictionary Queue : ICollection SortedList : IDictionary Stack : ICollection |
ICollection - BitArray, Queue, Stack IList - ArrayList IDictionary - HashTable, SortedList |
ArrayList class
[edit | edit source]ArrayList implements a variable-size IList that uses an array of objects to store the elements. A ArrayList has a ArrayList.Capacity, which is the allocated length of the internal array. The total number of elements contained by a list is its ArrayList.Count. As elements are added to a list, its capacity is automatically increased as required by reallocating the internal array.
Collection interfaces
[edit | edit source]- ICollection interface and IList interface
public interface ICollection { int Count { get; } bool IsSynchronized { get; } object SyncRoot { get; } void CopyTo (Array array, int index); } public interface IList { bool IsFixedSize { get; } bool IsReadOnly { get; } object this [ int index ] { get; set; } // TODO: Add methods. }
- IComparer interface and IEqualityComparer interface
- IDictionary interface and IDictionaryEnumerator interface
- IEnumerable interface and IEnumerator interface
public interface IEnumerable { IEnumerator GetEnumerator (); } public interface IEnumerator { Object Current { get; } bool MoveNext (); void Reset (); }
Iterators
[edit | edit source]Hashtable class
[edit | edit source]A Hashtable represents a dictionary with a constant lookup time that contains entries of associated keys and values. The type of each entry in a Hashtable is DictionaryEntry. A statement that exposes each element in the collection is required to iterate over this type.
CollectionBase class and ReadOnlyCollectionBase class
[edit | edit source]DictionaryBase class and DictionaryEntry class
[edit | edit source]Comparer class
[edit | edit source]Queue class
[edit | edit source]SortedList class
[edit | edit source]BitArray class
[edit | edit source]The System.Collections.BitArray implements a collection of boolean values. There are a number of different constructors for a BitArray. The BitArray( ) creates ... The methods of a BitArray allow a bitwise operation to be performed on the BitArray.
using System; using System.Collections; namespace OpenEd.Ms70536.Part1.Section2 { public class BitArrayExample { public static void Main () { BitArray bitArray = new BitArray (new byte [] {byte.Parse ("25")}); Console.WriteLine ("bitArray.Count: {0}", bitArray.Count); for (int i = 0; i < bitArray.Count; i++) Console.WriteLine ("bitArray [{0}]: {1}", i, bitArray [i]); } } }
Compiling and running this example gives the following output:
~/work/70-536/70-536.1/70-536.1.2> gmcs bitarrayfrombyte.cs ~/work/70-536/70-536.1/70-536.1.2> mono bitarrayfrombyte.exe bitArray.Count: 8 bitArray [0]: True bitArray [1]: False bitArray [2]: False bitArray [3]: True bitArray [4]: True bitArray [5]: False bitArray [6]: False bitArray [7]: False
Stack class
[edit | edit source]The stack is a collection supporting only the push, pop, and peek operations. The push method puts an object onto the end of the stack. The peek method returns the most recent object placed on the stack. The pop method removes the most recent object placed on the stack and returns it.
1.3 Improve type safety and application performance in a .NET Framework application by using generic collections
[edit | edit source]There is often a need to have a collection only store objects of a given type. For example an ArrayList might be used to store only strings.
ArrayList stringArray = new ArrayList (); stringArray.Add ("String 1."); stringArray.Add ("String 2."); stringArray.Add ("String 3.");
However this is not type safe as at any point in the lifetime of the stringArray object an object that is not a string can added.
There is also the convenience of having to cast down the items retreived from the stringArray.
string string2 = (string) stringArray [1];
In earlier versions of c# the only way to have type safe collections was either to wrap an existing collection or derive from an existing collection.
public class StringArray { private ArrayList stringArray; public StringArray () {} }
Collection.Generic interfaces
[edit | edit source]- Generic IComparable interface (Refer System Namespace)
- Generic ICollection interface and Generic IList interface
- Generic IComparer interface and Generic IEqualityComparer interface
- Generic IDictionary interface
- Generic IEnumerable interface and Generic IEnumerator interface
- IHashCodeProvider interface
Generic Dictionary
[edit | edit source]- Generic Dictionary class and Generic Dictionary.Enumerator structure
- Generic Dictionary.KeyCollection class and Dictionary.KeyCollection.Enumerator structure
- Generic Dictionary.ValueCollection class and Dictionary.ValueCollection.Enumerator structure
Generic Comparer class and Generic EqualityComparer class
[edit | edit source]Generic KeyValuePair structure
[edit | edit source]Generic List class, Generic List.Enumerator structure, and Generic SortedList class
[edit | edit source]Generic Queue class and Generic Queue.Enumerator structure
[edit | edit source]Generic SortedDictionary class
[edit | edit source]Generic LinkedList
[edit | edit source]- Generic LinkedList class
- Generic LinkedList.Enumerator structure
- Generic LinkedListNode class
Generic Stack class and Generic Stack.Enumerator structure
[edit | edit source]1.4 Manage data in a .NET Framework application by using specialized collections.
[edit | edit source]Specialized String classes
[edit | edit source]- StringCollection class
- StringDictionary class
- StringEnumerator class
Specialized Dictionary
[edit | edit source]- HybridDictionary class
- IOrderedDictionary interface and OrderedDictionary class
- ListDictionary class
Named collections
[edit | edit source]- NameObjectCollectionBase class
- NameObjectCollectionBase.KeysCollection class
- NameValueCollection class
CollectionsUtil
[edit | edit source]BitVector32 structure and BitVector32.Section structure
[edit | edit source]1.5 Implement .NET Framework interfaces to cause components to comply with standard contracts.
[edit | edit source]IComparable interface
[edit | edit source]IDisposable interface
[edit | edit source]IConvertible interface
[edit | edit source]ICloneable interface
[edit | edit source]IEquatable interface
[edit | edit source]IFormattable interface
[edit | edit source]1.6 Control interactions between .NET Framework application components by using events and delegates.
[edit | edit source]Delegate class
[edit | edit source]A delegate is similar to a typed function pointer.
The ThermoStat class
using System.Threading; namespace OpenEd.Ms70536.Part1.Section6 { public delegate void ThermostatChangedEventHandler(ThermostatState newState); public class Thermostat { private ThermostatState state = ThermostatState.Open; public ThermostatChangedEventHandler ThermostatChanged; public void MonitorTemperature() { while (true) { Thread.Sleep(2000); FlipState(); if (ThermostatChanged != null) { ThermostatChanged(state); } } } private void FlipState() { if (state == ThermostatState.Open) { state = ThermostatState.Closed; } else { state = ThermostatState.Open; } } } }
A delegate allows the act of calling a method to be delegated to someone else.
public delegate void TemperatureChangedEventHandler(double temperature); public class ClientServer { public static void Main () { Server server = new Server (); WriteMessage (server.GetMessage ()); // TODO: poll servers here. } public void WriteMessage (string message) { Console.WriteLine (message); } } public class EventHandlingClient { public static void Main () { Server server = new Server (); MessageReceived += new MessageReceivedEventHandler (WriteMessage); // TODO: loop waiting for servers here. } }
Delegate class - test driven
[edit | edit source]In this section we'll explore delegates using unit tests. The first question we'll look at is when are delgates created?
A delegate is created when an method is added to the invocation list. The delegate is distroyed when there are no more methods in the invocation list.
using NUnit.Framework; namespace OpenEd.Ms70536.Part1.Section6 { [TestFixture] public class ThermostatTests { [Test] public void AddingHandlerCreatesDelegate () { Thermostat thermostat = new Thermostat (); Assert.IsNull (thermostat.ThermostatChanged); thermostat.ThermostatChanged += new ThermostatChangedEventHandler (OnThermostatChanged); Assert.IsNotNull (thermostat.ThermostatChanged); thermostat.ThermostatChanged -= new ThermostatChangedEventHandler (OnThermostatChanged); Assert.IsNull (thermostat.ThermostatChanged); } public void OnThermostatChanged(ThermostatState newState) { } } }
EventArgs class
[edit | edit source]The EventArgs class is a base class for use in the pattern described in the next section. To pass arguments sub classes are derived from the EventArgs class.
public class ThermostatChangedEventArgs : EventArgs { private ThermostatState newState; public ThermostatChangedEventArgs (ThermostatState newState) { this.newState = newState; } public ThermostatState NewState { get { return newState; } } }
EventHandler delegates
[edit | edit source]The EventHanlder is part of a pattern for handling events that is aimed at reducing the proliferation of different delegates. In this pattern there is one delegate, the EventHandler delegate.
public delegate void EventHandler (object sender, EventArgs e)