Sie sind auf Seite 1von 102

IDictionaryEnumerator Interface

Enumerates the elements of a nongeneric dictionary.

Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
Syntax
Visual Basic (Declaration)
<ComVisibleAttribute(True)> _
Public Interface IDictionaryEnumerator _
Implements IEnumerator
Visual Basic (Usage)
Dim instance As IDictionaryEnumerator
C#
[ComVisibleAttribute(true)]
public interface IDictionaryEnumerator : IEnumerator

Remarks
vb#c#
The foreach statement of the C# language (for each in Visual Basic) hides the complexity of the enumerators.
Therefore, using foreach is recommended instead of directly manipulating the enumerator.

Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying
collection.

Initially, the enumerator is positioned before the first element in the collection. The Reset method also brings
the enumerator back to this position. At this position, calling the Current property throws an exception.
Therefore, you must call the MoveNext method to advance the enumerator to the first element of the
collection before reading the value of Current.

Current returns the same object until either MoveNext or Reset is called. MoveNext sets Current to the next
element.

If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the
collection and MoveNext returns false. When the enumerator is at this position, subsequent calls to MoveNext
also return false. If the last call to MoveNext returned false, calling Current throws an exception. To set
Current to the first element of the collection again, you can call Reset followed by MoveNext.

An enumerator remains valid as long as the collection remains unchanged. If changes are made to the
collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and
the next call to MoveNext or Reset throws an InvalidOperationException. If the collection is modified between
MoveNext and Current, Current returns the element that it is set to, even if the enumerator is already
invalidated.

The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection
is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads can still
modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during
enumeration, you can either lock the collection during the entire enumeration or catch the exceptions
resulting from changes made by other threads.

Notes to Implementers:
The Current property that is inherited from IEnumerator returns an Object that is a boxed DictionaryEntry,
similar to the return value of the Entry property.

Examples
This code example shows how to define a dictionary enumerator that implements the IDictionaryEnumerator
interface.
Visual Basic
Private Class SimpleDictionaryEnumerator
Implements IDictionaryEnumerator

' A copy of the SimpleDictionary object's key/value pairs.


Dim items() As DictionaryEntry
Dim index As Integer = -1

Public Sub New(ByVal sd As SimpleDictionary)


' Make a copy of the dictionary entries currently in the SimpleDictionary object.
items = New DictionaryEntry(sd.Count - 1) {}
Array.Copy(sd.items, 0, items, 0, sd.Count)
End Sub

' Return the current item.


Public ReadOnly Property Current() As Object Implements IDictionaryEnumerator.Current
Get
ValidateIndex()
Return items(index)
End Get
End Property

' Return the current dictionary entry.


Public ReadOnly Property Entry() As DictionaryEntry Implements IDictionaryEnumerator.Entry
Get
Return Current
End Get
End Property

' Return the key of the current item.


Public ReadOnly Property Key() As Object Implements IDictionaryEnumerator.Key
Get
ValidateIndex()
Return items(index).Key
End Get
End Property

' Return the value of the current item.


Public ReadOnly Property Value() As Object Implements IDictionaryEnumerator.Value
Get
ValidateIndex()
Return items(index).Value
End Get
End Property

' Advance to the next item.


Public Function MoveNext() As Boolean Implements IDictionaryEnumerator.MoveNext
If index < items.Length - 1 Then
index = index + 1
Return True
End If

Return False
End Function

' Validate the enumeration index and throw an exception if the index is out of range.
Private Sub ValidateIndex()
If index < 0 Or index >= items.Length Then
Throw New InvalidOperationException("Enumerator is before or after the collection.")
End If
End Sub

' Reset the index to restart the enumeration.


Public Sub Reset() Implements IDictionaryEnumerator.Reset
index = -1
End Sub

End Class

Public Function GetEnumerator() As IDictionaryEnumerator Implements IDictionary.GetEnumerator

'Construct and return an enumerator.


Return New SimpleDictionaryEnumerator(Me)
End Function

' ICollection Members


Public ReadOnly Property IsSynchronized() As Boolean Implements IDictionary.IsSynchronized
Get
Return False
End Get
End Property

Public ReadOnly Property SyncRoot() As Object Implements IDictionary.SyncRoot


Get
Throw New NotImplementedException()
End Get
End Property

Public ReadOnly Property Count() As Integer Implements IDictionary.Count


Get
Return ItemsInUse
End Get
End Property

Public Sub CopyTo(ByVal array As Array, ByVal index As Integer) Implements IDictionary.CopyTo
Throw New NotImplementedException()
End Sub

' IEnumerable Members


Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator

' Construct and return an enumerator.


Return Me.GetEnumerator()
End Function
End Class

C#
private class SimpleDictionaryEnumerator : IDictionaryEnumerator
{
// A copy of the SimpleDictionary object's key/value pairs.
DictionaryEntry[] items;
Int32 index = -1;
public SimpleDictionaryEnumerator(SimpleDictionary sd)
{
// Make a copy of the dictionary entries currently in the SimpleDictionary object.
items = new DictionaryEntry[sd.Count];
Array.Copy(sd.items, 0, items, 0, sd.Count);
}

// Return the current item.


public Object Current { get { ValidateIndex(); return items[index]; } }

// Return the current dictionary entry.


public DictionaryEntry Entry
{
get { return (DictionaryEntry) Current; }
}

// Return the key of the current item.


public Object Key { get { ValidateIndex(); return items[index].Key; } }

// Return the value of the current item.


public Object Value { get { ValidateIndex(); return items[index].Value; } }

// Advance to the next item.


public Boolean MoveNext()
{
if (index < items.Length - 1) { index++; return true; }
return false;
}

// Validate the enumeration index and throw an exception if the index is out of range.
private void ValidateIndex()
{
if (index < 0 || index >= items.Length)
throw new InvalidOperationException("Enumerator is before or after the collection.");
}

// Reset the index to restart the enumeration.


public void Reset()
{
index = -1;
}
}
public IDictionaryEnumerator GetEnumerator()
{
// Construct and return an enumerator.
return new SimpleDictionaryEnumerator(this);
}
#endregion

#region ICollection Members


public bool IsSynchronized { get { return false; } }
public object SyncRoot { get { throw new NotImplementedException(); } }
public int Count { get { return ItemsInUse; } }
public void CopyTo(Array array, int index) { throw new NotImplementedException(); }
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
// Construct and return an enumerator.
return ((IDictionary)this).GetEnumerator();
}
#endregion
}

Event
Summary
An event is basically a list of delegates. Technically, it is a multicast delegate. However, the event keyword
allows the compiler to encapsulate the delegate to control how it is accessed.

The object that has the event is called the publisher. The object that handles the event is called the
subscriber. An event allows a publisher to call a subscriber's event handler without knowing anything about
the subscriber.

For example, a Button object with a Click event can call all the ClickEventHandlers without knowing the class
or method names which handle the event.

It is the subscriber's responsibility to subscribe to the event. The publisher simply raises the event at the
appropraite time. Whenever the event is raised, each delegate that is in the event's list will be called.

Remarks
The event keyword encapsulates the event delegate. With it, the compiler only allows += and -= operations
outside the class. Therefore, only the publisher can access the delegate object directly to call it or edit the list
of delegates.

Code Examples
.Net Event Conventions:

Name delegates used for an event type with a suffix of "EventHandler"

Name custom EventArgs with a suffix of "EventArgs" and inherit from EventArgs

EventHandler delegates should always have two parameters: object sender, and ___EventArgs e

Example Names:

// Event Handler Delegate Declaration


public delegate void MouseClickedEventHandler( object sender, MouseClickedEventArgs e );

// Event Args Declaration


public class MouseClickedEventArgs : EventArgs
{
//...
}

// Event Declaration
public event MouseClickedEventHandler MouseClicked;
Declare a basic event

public event EventHandler Changed;Declare a Mouse Clicked event

public event MouseClickEventHandler MouseClicked;Subscribe to an event


public void Subscribe()
{
// Subscribe to the event
btnCancel.Click += new EventHandler( CancelClick );
}

// The event handler


void CancelClick( object sender, EventArgs e )
{
//...
}Declare a delegate and an event with custom EventArgs

// Declare a delegate inside the namespace


public delegate void StatusChangedEventHandler( object sender, StatusChangedEventArgs e );

// StatusChangedEventArgs is at the bottom of this example

// The event publisher


public class ClassWithStatus
{
// Declare the event
public event StatusChangedEventHandler StatusChanged;
}

// Declare the custom event args class


// It should inherit from EventArgs
public class StatusChangedEventArgs : EventArgs
{
private readonly bool _isDone;

public StatusChangedEventArgs( bool isDone )


{
_isDone = isDone;
}

public bool IsDone


{
get
{
return _isDone;
}
}
}Declare an event that uses generic EventHandler with custom EventArgs

// The event publisher


public class TreeNode
{
// Declare the event
public event EventHandler<ExpandedEventArgs> Expanded;
}

// The custom event args class


public class ExpandedEventArgs : EventArgs
{
private readonly TreeNode _expandingNode;

public StatusChangedEventArgs( TreeNode expandingNode )


{
_expandingNode = expandingNode;
}

public TreeNode ExpandingNode


{
get
{
return _expandingNode;
}
}
}

Exam 70-536 Study Guide: Skill Set 1

This is the first skill set for the the Microsoft .NET Framework 2.0—Application Development Foundation Exam.
This skill set involves using the built-in system data types, collections of data types, interfaces, and delegates
and events.

Developing applications that use system types and collections


Manage data in a .NET Framework application by using the .NET Framework 2.0 system types. (System)
Manage a group of associated data using collections in a .NET Framework application. (System.Collections)
Use generic collections to improve type safety and application performance in a .NET Framework application.
(System.Collections.Generic)
Use specialized collections to manage data in a .NET Framework application. (System.Collections.Specialized)
Implement .NET Framework interfaces to cause components to comply with standard contracts. (System)
Use events and delegates to control interactions between .NET Framework application components. (System)

Exception classes

When writing any piece of software, at some stage errors occur when the application is run. This is through no
fault in the programming of the code, but rather through unexpected actions on the part of the user.
Unexpected actions may include selecting a file that does not exist or entering a letter where a number is
expected.

These unexpected actions can be handled in one of two ways, either by preemptive programming or by using
exceptions. The .NET Framework provides an Exception class in the System namespace to handle exceptions.

Preemptive programming requires the programmer to think about everything that could possibly go wrong
when the application is run. Let us consider the first of the two examples cited above. To find out if a file
exists, we can invoke the Exists() function of the File class, passing to it the string supplied to us by the user:

if ( !File.Exists (file_name))
{
// The source file does not exist
}
else
{
// The source file exists
}The if statement catches the error; but, what should we do with it? What about if the if statement was not
inverted? This would cause a programming bug that would not be caught until runtime and would cause an
exception. When a program error occurs, either the system or the currently executing application reports it by
throwing an exception containing information about the error. Once thrown, an exception is handled by the
application or by the default exception handler.
Even if you remove all bugs and anticipate all user errors, you will still run into predictable but unpreventable
problems, such as running out of memory or attempting to open a file that no longer exists. You cannot
prevent exceptions, but you can handle them so that they do not bring down your program.

Benefits of exceptions
Exceptions provide the ability to handle or clean up code in a localized place. Also, they allow clean-up code to
execute in case of error. The application becomes easier to write and maintain when clean-up code is in a
centralized place.

Also—and maybe more importantly—, exceptions can be used to find bugs within the code; because, the CLR
walks up the stack of the thread to get the call history. With this, it is possible to find the location of the
failure within the code. Further, it is possible to add additional information within the exception, so that a
developer can describe the kind of error more precisely.

The biggest problem with exceptions is performance because of some information overhead. So, they should
be used only where preemptive programming is inappropriate. Unfortunately, most developers tend to use
exceptions improperly—i.e. catch (Exception e); which will be discussed later—or too seldom, so debugging
proves harder.

Using exceptions
Execptions are used within the try-, catch-, and finally-code blocks. The Exception is created and thrown
within the try-block.

If the Exeption is thrown, the code within the try-block stops and the finally-block executes.

After this, the first match to a sequence of catch-blocks gets executed, bringing the application into a stable
state; because, the code in the try-block didn't finish.

The structure of this looks like the following:

void example()
{
try
{
// Here is where the Exception would be thrown
}
catch (ArgumentOutOfRangeException e)
{
// This block executes if the Exception is of type
// ArgumentOutOfRangeException. Otherwise, the program
// jumps to the next catch-block.
}
catch (InvalidCastException e)
{
// This block executes if the Exception is of type
// InvalidCastException. The Exception is stored
// within the Variable "e". This is needed e.g. to query
// and extend the Error Message of the Exception.
}
catch (Exception e)
{
// Because all Exceptions in .NET derive from Exception,
// this block will handle all .NET Exceptions.

// This kind of Exception cannot be handled and must be


// rethrown. Think of an OutOfMemoryException, where
// creating a Window showing the Exception makes it even
// worse.

throw;
}
catch
{
// Catches all kinds of exceptions, even when they are not
// CLS-comform, which can appear only when calling
// unmanaged code.

// This can not be handled correctly, either.


throw;
}
finally
{
// This code will execute in any case,
// whether an Exception was thrown or not.
}
}The catch block can handle the Exception in one of three ways:

Rethrow the same exception to notify the code which is prior in the call stack.
Throw another exception with more precise information. The current Exception can be appended.
Handle the exception and continue with the code after the try/catch/finally-block.
Important:

Never handle an Exception of type System.Exception, because this is not—or, at least, hardly—possible.
Examples are:
OutOfMemoryException
Occurs when the CLR has no free memory available to create new objects on the Heap. Even the garbage
collector does not help at this point. The best thing you can do is to terminate the program (thread). If you
want to develop a server application, it is best to develop also a watch dog program or to register the
program as a Windows service, so that it will restart the program or even the entire server.
StackOverflowException
Similar to the OutOfMemoryException; but this time, there is no space on the Stack. This makes it also
impossible to call the finally-block. Therefore the program can be in an undefined state and should be
terminated.
ExecuteEngineException
This Exception throws when the CLR detects an error like a corrupted data-structure (e.g. a buffer overflow)
or a bug within the CLR itself. Anyway, in that case, the CLR will call a debugger or terminate the whole
process without executing any catch- or finally-blocks.
Also, catching such an Exception and checking the type of it afterwards is possible; but, it is not a pretty
programming style.
The System.Exception class
The System.Exception class is small class representing information about the kind of Exception. The properties
are:

Message
A string representing a human-readable message.
Source
The name of the assembly where the exception was thrown.
Not available in the Mobile .Net Framework.
StackTrace
Names of the calling functions as found on the call stack.
TargetSite
The method that throws the Exception originally.
Not available in the Mobile .Net Framework.
HelpLink
A link to a resource (e.g. a Web site or a help file) which provides further information.
Not available in the Mobile .Net Framework.
InnerException
This field is normally set to null. If not, this indicates that this Exception was thrown because of another
Exception whith is now stored within this property. Additional to this property, you can also use the
GetBaseException() function which returns the innermost Exception.
HResult
This is the HResult whitch will get returned from a COM object. This property is only needed when
interoperating with COM code.
Handling exceptions
As stated before we have three possibilities to handle a Exception:

Rethrow
Throw new exception
Handle the exception
We will look at some examples in the following sections.

Rethrow an Exception
One way to use Exception is to catch an Exception and run exception-specific code. When this is done, the
same exception is thrown again and "bubbling up" the call stack.

public String ReadFirstLine (String FileName)


{
try
{
FileStream fs = new FileStream (FileName, FileMode.Open);
}
catch (Exception e)
{
// override the Message of the Exception
e.Message = "Could not open the file.";

// rethrow the same exception


throw;
}

// the file is open now

try
{
String FirstLine = fs.ReadLine();
}
catch (Exception e)
{
e.Message = "Could not read first line of file.";
throw;
}
finally
{
// close the FileStream in each case
fs.Close();
}
return FirstLine;
}Even if we catch an System.Exception here, it is not a problem; because, we can simply rethrow it. Another
problem you should respect within catch(Exception e) blocks is that you should avoid creating new objects
within the heap (reference types). Remember the OutOfMemoryException example.
Sometimes, it is necessary to set data back to its original state when an exception occurs. In that case, you
create a backup of the properties you want to change and restore them in case of a exception.

private Byte[10] ReadNextTenBytes(FileStream fs)


{
Int64 PositionBeforeOutput = fs.Position;
try
{
var Output = new Byte[10];
fs.Read (Output, fs.Position, 10);
}
catch
{
fs.Position = PositionBeforeOutput;
throw;
}
return Output;
}Throw a new Exception
Sometimes the Exception thrown by a function does not describe the core of the problem well enough. In such
a case, you catch the exception and throw a more describing one instead.

public Int32 Inverse(Int32 Number)


{
Int32 Inverse;
try
{
Inverse = 1 / Number;
}
catch (DivideByZeroException e)
{
ArgumentOutOfRangeException ae =
new ArgumentOutOfRangeException (
"Number can't be Zero", e);
throw ae;
}
return Inverse;
}Notice that when throwing a new exception or when rethrowing the original Exception using code like catch
(Exception e){throw e;} properties like StackTrace and Source will get overridden by the information of the
current function.

Also, in most cases, you should set the InnerException property (second argument of the constructor) for
further reference.

Handle the Exception


In some special cases, it is possible to bring the application into a stable state, even when an Exception has
occurred.

public Int32[] ParseNumbers(String[] Numbers)


{
Int32[] ParsedNumbers = new Int32[];
Int32 ParsedNumber;
int elements = 0;

foreach (Int32 Number in Numbers)


{
try
{
ParsedNumber = Int32.Parse(Number);
}
catch (FormatException e)
{
continue;
}
catch (OverflowException e)
{
continue;
}
ParsedNumbers[elements++] = ParsedNumber;
}
return ParsedNumbers;
}This code takes an array of integers which are presented as a String array. The code tries to parse every
string within this array one after the other. If this fails, the Int32.Parse() method will probably throw an
Exception of type FormatException or OverflowException. This means the string is not parseable. This does
not matter in that case; and, we simply repeat with parsing the next String in the array.

Other exceptions will not be handled. They continue bubbling up the call stack.

Notice, that in this example, we do not need access to the Exception; so, we could rewite, e.g. catch
(FormatException e) as catch(FormatException).

Catch filter
In C#, the catch block filters for a specific type of Exception and runs the first match. But, the .NET CLR
supports also more complex catch filters which you can use from Visual Basic .NET, C++ with managed
extensions, or IL.

In VB .Net this might look like:

Catch e as Exception When x = 0In that example, the catch code executes only if the Exception is of type
System.Exception and the variable x is equal to zero. In C#, you need to rewrite this using an additional if
block.

Creating and throwing an Exception


The first thing when wanting to create a Exception is to find the best fitting one for your purpose. Therefore
you can use the List Exceptions Program to find all the common ones. Then, read the result and select one. If
you want to be more specific by providing a more meaningful name or additional properties, derive a new
Exception from the next best fitting one.

Note, that in the worst case the best fitting Exception is not System.Exception or System.SystemException,
which is a reserved behavior for the .NET Framework internal exceptions from which you should derive, but
System.ApplicationException.

Custom exceptions should always be serializeable, so that the exception can also used in an distributed
environment like a Web service.

If you decided on one or created an exception, you can create a new exception like any other class. Then you
simply throw that Exception using the throw-Keyword.

For example:

ArgumentOutOfRangeException e =
new ArgumentOutOfRangeException();
e.Message = "Value must be within 1 and 100";
throw e;or
ArgumentOutOfRangeException e =
new ArgumentOutOfRangeException
("Value must be within 1 and 100");
throw e;or

throw new ArgumentOutOfRangeException


("Value must be within 1 and 100");[edit]Performance
As previously stated, exception handling comes with a performance penalty. Using a HRESULT or a similar
special return value is more efficient but inflexible when it comes to management, debugging, or reuse of the
code.

Exception handling in a managed runtime environment like the .NET or Java runtimes is more efficient that in
an unmanaged environment like C++; because, the C++ Compiler has to write bookkeeping code (i.e. to
track objects on the heap), whereas in a managed environment much of this bookkeeping code is implicit (i.e.
garbage collection). The exact overhead for Exception handling in .NET is hard to predict, because it depends
how the compiler on the target platform implements it. Some compilers are using lookup tables, others
generate special methods for this task. When it comes to performance tests you should do them on the target
platform.

In Microsoft Windows, you can use PerfMon.exe, or the System Monitor ActiveX control. When using PerfMon,
you select .Net CLR Exceptions as Performance Object and then select the statistics which you are most
interrested in.

Unhandled Exceptions

Unhandeled Exception Dialog


Visual Studio 2005 Exceptions Handling
Visual Studio 2005 Exceptions DialogIf a exception occurs the CLR traverses up the call stack looking for a
matching catch expression. If the CLR doen't finds a matching one, or the Execption gets rethrown eachtime,
the Exception bubbles out of the Main() method. In that case Windows handels the Exception.

First, Windows is searching for a fitting registered debugger like Visual Studio which can handle the Exception.
Visual Studio has very powerfully mechanisms, so ie. for a debug-compiled version Visual Studio jumps
directly to the place within the source where the Exception has occured. Further Visual Studio 2005 provides
mechanisms to look at the current values of all the Variables which provides an immense programming-
advance compared to most other debuggers. Release compiled Version of your Program doesn't include the
additional debug-information needed to map the code to the source. This leads to faster execution, but on the
one hand you have to debug within IL. At best it is possible to find the right function within the source, based
on the information within the exception (Exception.StackTrace). Also the mapping of the value of the variables
gets lost if they are not stored within the exception too (remember Exception.ParamName and
Exception.ActualValue).

The debugger of Microsofts Visual Studio 2005 offers special exception handling support. The Dialog providing
the settings for this can be found in Debug/Exceptions from the Menubar. A detailed description can be found
within the documentation of Visual Studio.

Logging Exceptions
You can log exceptions with System.Diagnostics.EventLog if the user uses Windows 2k/XP/2003/Vista. A very
good thing when working with public available versions of your program is to set up a server running a public
available EventLog, or - on Unix Systems - a special developed WebService to whitch you can report. On
uncritical Exceptions you can also present the user a special Window providing text-fields to give additional
information (E-Mail Address for contact; Information about the user has done with your Application; etc. - but
don't ask for things like the used operating system; figure it out by code where possible). At least it is a much
smarter approach than providing just a E-Mail Address or a Webforum, as most developers do, because the
error-report is more problem oriented and goes directly to the responsible programmer. If you want to do
remote logging let the user decide if she really wants to send the report or not.
Important: It is not possible to create a new window when there is ie. a out-of-memory Exception. If you try
it you will get a new out-of-memory Exception, trying to create a new window, creating a new Exception....
This can cause a hangup of the operating-system.
Exception policies
It is also possible to register an Event Handler for unhandled exceptions. The code below gives an example,
how this might look like. The Example works also within threads, so you don't really have to terminate the
whole application which can give you the possibility to recover, make an failure report, and maybe respawn
the thread.

using System;
using System.Diagnostics;
using System.Windows.Forms;

class Application
{
static void Main()
{
// Register an Event Handler whitch
// handeles the unhandeled Exception
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler
(OnUnhandledExceptionPolicy);
try
{
// Application code comes here
}
finally
{
// Finalization code comes here
}
}

static void OnUnhandledExceptionPolicy


(Object Sender, UnhandledExceptionEventArgs e)
{
String InformationForLogging;
Exception ex = e.ExceptionObject as Exception;

if (ex != null)
{
// The unhandled Exception is CLS compliant
// Extract the Information you want to know
InformationForLogging = ex.ToString();
}
else
{
// The unhandeled Exception is not CLS compliant
// You can only handle this Exception as Object
InformationForLogging = String.Format(
"Type: {0}{2}String: {1}",
e.ExceptionObject.GetType(),
e.ExceptionObject.ToString(),
Environment.NewLine)
}

#if DEBUG
if (!e.IsTerminating)
{
// Exception occurred in a thread pool or finalizer thread
// Debugger launches only explicitly
} else
{
// Exception occurred in managed thread
// Debugger will also launch when not launched explicitly
}
// explicitly launch the debugger (Visual Studio)
Debugger.Launch();

#else

// This is a final release;


// logging is done to Syslog and over the Web if possible
// Debugger is mostly not available

if (!e.IsTerminating)
{
// Exception occurred in a thread pool or finalizer thread
// Application keeps open
}
else
{
// Exception occurred in managed thread
// Application is closing, so you should log now
}
#endif
}
}Controlling CLR unhandled Exception behavior
When a managed thread throws a unhandled Exception, the CLR looks into the registry for the kind of
debugging. The Registry Key for this is named DbgJITDebugLaunchSetting and can be found in
HKEY_LOCAL_MACHINE\Software\Microsoft\.NetFramework\.

DbgJITDebugLaunchSetting Value Behavior


0 Displays a dialog asking the user for debugging.
If the user chooses to do not, the UnhandledException gets thrown within the AppDomain. If there is no
EventHandler for this the CLR displays the Stacktrace.
In the case of a CUI-Application (Console), the Stacktrace will get shown on the console. A GUI-Application
(WinForms) shows the Stacktrace within a new window.
If the user chooses to debug, the CLR looks for the Key DbgManagedDebuger with can be found also in
HKEY_LOCAL_MACHINE\Software\Microsoft\.NetFramework\ and starts this debugger.

1 No dialog box is presented do the user. The UnhandledException gets thrown immediately.
2 No dialog box is presented do the user. The CLR starts the debugger.

Next to the settings for the debugger in the registry it is also possible to enable or disable an JIT-Debugger by
setting jitDebugging within the applications .config file.

Unhandled exceptions in different application types


Where and how the output of an unhandeled Exception occurs depends on the application type. There are
Console Applications (CUI), WinForms Applications (GUI; including DirectX), ASP.Net Applications, and
ASP.Net WebServices.

Console
Event Handling of Console Applications are the easiest to understand, because there is no special Handling by
the CLR. The Exception is leaving the Applications Thread if not caught. The CLR opens a window asking for
debug or exit the application. If the user chooses to debug, the debugger starts. If the user chooses to close,
the Application exits and the Exception is serialized and written to the console.

Windows Forms
In a Windows Forms application, the Run-method of the System.Windows.Forms.Application-Class runs a loop
within a new thread. This loop dispatches messages of the type System.Windows.Forms.NativeWindow which
contains a try/catch block. Within the try-block of this, Microsoft Windows WndProc-Method is called to create
the Window.

The catch block of a Window calls the virtual OnThreadException-Method of the window when a CLR-
Excception occurs. In the case of a control this method calls the OnThreadException-Method from the
Application. By default this calls a Window giving the user the possibility to continue or quit the application. If
the user continues the application will be in an undefinded state, so he should save his work when possible -
at best in a new file to avoid corruption of the original file - and restart the application.

It is possible to override this window by providing an event handler of type


System.Threading.ThreadExceptionEventHandler and registering it for the ThreadException-Event of the
Application.

Because WindowsForms handle only CLR-Exceptions you might want to create also another
ThreadExceptionEventHandler for this and register it for the UnhandeledException-Event of the Application.

ASP.Net Web Forms


In ASP.Net Web Forms, ASP.Net itself catches most Exceptions using its own try-block.

Therefore it is possible to register a callback method using the Error-Event of


System.Web.UI.TemplateControl. The TemplateControl-Class itself is the base class of System.Web.UI.Page
and System.Web.UI.UserControl, so each Page and Control exposes this Event too.

On the other hand it is possible to receive notifications about unhandeled exceptions for a page by registering
a callback method. You can register this method Application wide within the Error-Property of the
System.Web.Application-Class.

Also, ASP.Net offers options to create a dump about the Exception to a Webpage.

ASP.Net Web services


Web services have also a easy way of handling Exceptions. ASP.Net catches the Exception and throws a new
System.Web.Services.Protocols.SoapException. This SoapException is serialized to XML, representing a SOAP-
Fault. This gets understood by other SOAP Clients independently of the Platform or the Programming
Environment.

If the client is a .NET Framework application the SOAP-Fault is deserialized into a SoapException and thrown
at the place where the WebService-Call occurred. This Exception can then get handled like any other
exception.

Fields and Properties

Fields
Fields in a class are used to hold data. Fields can be marked as public, private, protected, internal, or
protected internal. A field can optionally be declared static. A field can be declared readonly. A read-only field
can only be assigned a value during initialization or in a constructor.

A field can be given an initial value by using the assignment operator when the field is declared.

public class Car


{
public string make = "Ford";
}Fields are initialized immediately before the constructor for the object instance is called, so if the constructor
assigns the value of a field, it will overwrite any value given during field declaration.

public class Car


{
public string make = "Ford";

public Car()
{
make = "Alfa";
}
}These examples use fields that are public, but this is not recommended in practice. Fields should generally
be private with access to fields given by using properties.

Properties
Properties allow users to access class variables as if they were accessing member fields directly, while actually
implementing that access through a class method.

The user wants direct access to the variables of the object and does not want to work with methods. The class
designer, however, wants to hide the internal variables of his class in class members, and provide indirect
access through a method. By decoupling the class variables from the methods that access those variables, the
designer is free to change the internal state of the object as needed.

Coding properties
The code below shows how to create a private variable with its associated properties.

// private member variables


private int hour;

// create a property
public int Hour
{
get { return hour; }
set { hour = value; }
}You then access the properties in the following manner:

// Get the current value of hour to local variable iHour


int iHour = aClass.Hour;

// Increment iHour
iHour++;

// Write iHour back to hour


aClass.Hour = iHour;

Properties in C# 2.0
In C# 2.0 you can set the accessibility of get and set.

The code below shows how to create a private variable with an internal set and public get. The Hour property
can now only be set from code in the same module (dll), but can be accessed by all code that uses the module
(dll) that contains the class.

// private member variables


private int hour;

// create a property
public int Hour
{
get { return hour; }
internal set { hour = value; }
}

Asymmetric Accessor Accessibility

The get and set portions of a property or indexer are called accessors. By default these accessors have the
same visibility, or access level: that of the property or indexer to which they belong. For more information,
see accessibility levels. However, it is sometimes useful to restrict access to one of these accessors. Typically,
this involves restricting the accessibility of the set accessor, while keeping the get accessor publicly
accessible. For example:

private string name = "Hello";

public string Name


{
get
{
return name;
}
protected set
{
name = value;
}
}

In this example, a property called Name defines a get and set accessor. The get accessor receives the
accessibility level of the property itself, public in this case, while the set accessor is explicitly restricted by
applying the protected access modifier to the accessor itself.

Restrictions on Access Modifiers on Accessors


Using the accessor modifiers on properties or indexers is subject to these conditions:

You cannot use accessor modifiers on an interface or an explicit interface member implementation.

You can use accessor modifiers only if the property or indexer has both set and get accessors. In this case,
the modifier is permitted on one only of the two accessors.

If the property or indexer has an override modifier, the accessor modifier must match the accessor of the
overridden accessor, if any.

The accessibility level on the accessor must be more restrictive than the accessibility level on the property or
indexer itself.

Access Modifiers on Overriding Accessors


When you override a property or indexer, the overridden accessors must be accessible to the overriding code.
Also, the accessibility level of both the property/indexer, and that of the accessors must match the
corresponding overridden property/indexer and the accessors. For example:

public class Parent


{
public virtual int TestProperty
{
// Notice the accessor accessibility level.
protected set { }
// No access modifier is used here.
get { return 0; }
}
}
public class Kid : Parent
{
public override int TestProperty
{
// Use the same accessibility level as in the overridden accessor.
protected set { }

// Cannot use access modifier here.


get { return 0; }
}
}

Implementing Interfaces
When you use an accessor to implement an interface, the accessor may not have an access modifier.
However, if you implement the interface using one accessor, such as get, the other accessor can have an
access modifier, as in the following example:

public interface ISomeInterface


{
int TestProperty
{
// No access modifier allowed here
// because this is an interface.
get;
}
}

public class TestClass : ISomeInterface


{
public int TestProperty
{
// Cannot use access modifier here because
// this is an interface implementation.
get { return 10; }

// Interface property does not have set accessor,


// so access modifier is allowed.
protected set { }
}
}

Accessor Accessibility Domain


If you use an access modifier on the accessor, the accessibility domain of the accessor is determined by this
modifier.

If you did not use an access modifier on the accessor, the accessibility domain of the accessor is determined
by the accessibility level of the property or indexer.

Example
The following example contains three classes, BaseClass, DerivedClass, and MainClass. There are two
properties on the BaseClass, Name and Id on both classes. The example demonstrates how the property Id on
DerivedClass can be hidden by the property Id on BaseClass when you use a restrictive access modifier such
as protected or private. Therefore, when you assign values to this property, the property on the BaseClass
class is called instead. Replacing the access modifier by public will make the property accessible.

The example also demonstrates that a restrictive access modifier, such as private or protected, on the set
accessor of the Name property in DerivedClass prevents access to the accessor and generates an error when
you assign to it.

public class BaseClass


{
private string name = "Name-BaseClass";
private string id = "ID-BaseClass";

public string Name


{
get { return name; }
set { }
}

public string Id
{
get { return id; }
set { }
}
}

public class DerivedClass : BaseClass


{
private string name = "Name-DerivedClass";
private string id = "ID-DerivedClass";

new public string Name


{
get
{
return name;
}

// Using "protected" would make the set accessor not accessible.


set
{
name = value;
}
}

// Using private on the following property hides it in the Main Class.


// Any assignment to the property will use Id in BaseClass.
new private string Id
{
get
{
return id;
}
set
{
id = value;
}
}
}

class MainClass
{
static void Main()
{
BaseClass b1 = new BaseClass();
DerivedClass d1 = new DerivedClass();

b1.Name = "Mary";
d1.Name = "John";

b1.Id = "Mary123";
d1.Id = "John123"; // The BaseClass.Id property is called.

System.Console.WriteLine("Base: {0}, {1}", b1.Name, b1.Id);


System.Console.WriteLine("Derived: {0}, {1}", d1.Name, d1.Id);

// Keep the console window open in debug mode.


System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
/* Output:
Base: Name-BaseClass, ID-BaseClass
Derived: John, ID-BaseClass
*/

Fields

A field is a variable of any type that is declared directly in a class or struct. Fields are members of their
containing type.

A class or struct may have instance fields or static fields or both. Instance fields are specific to an instance of
a type. If you have a class T, with an instance field F, you can create two objects of type T, and modify the
value of F in each object without affecting the value in the other object. By contrast, a static field belongs to
the class itself, and is shared among all instances of that class. Changes made from instance A will be visibly
immediately to instances B and C if they access the field.

Generally, you should use fields only for variables that have private or protected accessibility. Data that your
class exposes to client code should be provided through methods, properties and indexers. By using these
constructs for indirect access to internal fields, you can guard against invalid input values. A private field that
stores the data exposed by a public property is called a backing store or backing field.

Fields typically store the data that must be accessible to more than one class method and must be stored for
longer than the lifetime of any single method. For example, a class that represents a calendar date might
have three integer fields: one for the month, one for the day, and one for the year. Variables that are not
used outside the scope of a single method should be declared as local variables within the method body itself.

Fields are declared in the class block by specifying the access level of the field, followed by the type of the
field, followed by the name of the field. For example:

public class CalendarEntry


{
// private field
private DateTime date;

// public field (Generally not recommended)


public string day;

// Public property exposes date field safely.


public DateTime Date
{
get
{
return date;
}
set
{
if(value.Year > 1980 || value.Year <= 2008)
{
date = value;
}
else
throw new ArgumentOutOfRangeException();
}

// Public method also exposes date field safely.


public void SetDate(string dateString)
{
DateTime dt = Convert.ToDateTime(dateString);

if (dt.Year > 1980 || dt.Year <= 2008)


{
date = dt;
}
else
throw new ArgumentOutOfRangeException();
}

public TimeSpan GetTimeSpan(string dateString)


{
DateTime dt = Convert.ToDateTime(dateString);

if (dt != null && dt.Ticks < date.Ticks)


{
return date - dt;
}
else
throw new ArgumentOutOfRangeException();

}
}

To access a field in an object, add a period after the object name, followed by the name of the field, as in
objectname.fieldname. For example:

CalendarEntry birthday = new CalendarEntry();


birthday.day = "Saturday";
A field can be given an initial value by using the assignment operator when the field is declared. To
automatically assign the day field to "Monday", for example, you would declare day as in the following
example:

public class CalendarDateWithInitialization


{
public string day = "Monday";
//...
}

Fields are initialized immediately before the constructor for the object instance is called. If the constructor
assigns the value of a field, it will overwrite any value given during field declaration. For more information,
see Using Constructors (C# Programming Guide).

Note:
A field initializer cannot refer to other instance fields.

Fields can be marked as public, private, protected, internal, or protected internal. These access modifiers
define how users of the class can access the fields. For more information, see Access Modifiers (C#
Programming Guide).

A field can optionally be declared static. This makes the field available to callers at any time, even if no
instance of the class exists. For more information, see Static Classes and Static Class Members (C#
Programming Guide).

A field can be declared readonly. A read-only field can only be assigned a value during initialization or in a
constructor. A static readonly field is very similar to a constant, except that the C# compiler does not have
access to the value of a static read-only field at compile time, only at run time

Generic Lists
List class
List<T> is the most useful collection. It is basically an array that can change size dynamically. Since it is a
generic collection, it is also type safe.

Code Examples
Add items to a list

List<int> numbers = new List<int>();

numbers.Add( 1 );
numbers.Add( 2 );
numbers.Add( 3 );Does a list contain an item

if( numbers.Contains( 3 ){
//...
}Remove items from a list

numbers.Remove( 1 );
numbers.Remove( 2 );
numbers.Remove( 3 );Remove the first 3 items in a List

// When an item is removed all,


// items following it are moved to fill the gap
// So in order to remove the first 3 items,
// Remove from the first item 3 times
numbers.RemoveAt( 0 );
numbers.RemoveAt( 0 );
numbers.RemoveAt( 0 );[edit]List.Enumerator structure
The List.Enumerator implements the IEnumerator<T> interface for a generic List.

See IEnumerator and IEnumerator<T>.

Generic Queue
FIFO
The Queue class allows the implementation of a FIFO (First-In-First-Out) storage system

Due to Queue being a collection it can easily be simulated using a List. This is handy to remember so that if
find yourself trying to implement such a system just remember that one already exists!

Generic.Queue vs Queue
The Collections.Generic.Queue should always be chosen over the Collections.Queue class to promote type
safety. However, their basic operation is identical in every area apart from when using an enumerator.

Usage of Generic Queue


System.InvalidOperationException thrown if no check for within bounds.

byte data = 42;


Queue<byte> myQueue = new Queue<byte>();

myQueue.Enqueue(data);

if (myQueue.Count > 0) //Check within bounds


{
data = myQueue.Dequeue();
}
Simulation of Queue using Generic List
Note that by simulating a queue like this means that all elements are open for access and therefore the queue
can be abused.

System.ArgumentOutOfRangeException thrown if no check for within bounds

byte data = 42;


List<byte> myList = new List<byte>();

myList.Add(data); //Enqueue

if (myList.Count > 0) //Check within bounds


{
//Dequeue
data = myList[0];
myList.RemoveAt(0);
}
Enumerator
The Enumerator or more precisely the Queue<T>.Enumerator allows simple iteration through the elements of
the Queue.

Note: To protect the Queue from abuse the enumerator only allows read operations.
Unlike the IEnumerator (returned by Collections.Queue) the Queue<T>.Enumerator does not provide a Reset
method.

The most important thing to remember when using an enumerator is not to modify the Queue once an
instance of the enumerator has been created. Therefore the fool-proof way of ensuring this is to stick it inside
its own method.

using System;
using System.Collections.Generic;

static void queueEnumeratorEG()


{
Queue<byte> myQueue = new Queue<byte>();

myQueue.Enqueue(1);
myQueue.Enqueue(2);
myQueue.Enqueue(3);
myQueue.Enqueue(4);

queuePrint(myQueue);

myQueue.Dequeue();
myQueue.Dequeue();

queuePrint(myQueue);
}

static void queuePrint(Queue<byte> myQueue)


{
Queue<byte>.Enumerator mqEnumerator = myQueue.GetEnumerator();

while (mqEnumerator.MoveNext())
{
Console.WriteLine(mqEnumerator.Current.ToString());
}
Console.WriteLine();
}The alternative is to use a foreach statement which uses the enumerator behind the scenes.

Queue<(Of <(T>)>) Class

Represents a first-in, first-out collection of objects.


Namespace: System.Collections.Generic
Assembly: System (in System.dll)

Visual Basic (Declaration)


<SerializableAttribute> _
<ComVisibleAttribute(False)> _
Public Class Queue(Of T) _
Implements IEnumerable(Of T), ICollection, IEnumerable
Visual Basic (Usage)
Dim instance As Queue(Of T)

C#
[SerializableAttribute]
[ComVisibleAttribute(false)]
public class Queue<T> : IEnumerable<T>, ICollection,
IEnumerable

Type Parameters
T
Specifies the type of elements in the queue.

Remarks
Queues are useful for storing messages in the order they were received for sequential processing. Objects
stored in a Queue<(Of <(T>)>) are inserted at one end and removed from the other.

The capacity of a Queue<(Of <(T>)>) is the number of elements the Queue<(Of <(T>)>) can hold. As
elements are added to a Queue<(Of <(T>)>), the capacity is automatically increased as required by
reallocating the internal array. The capacity can be decreased by calling TrimExcess.

Queue<(Of <(T>)>) accepts nullNothingnullptra null reference (Nothing in Visual Basic) as a valid value for
reference types and allows duplicate elements.

Examples
The following code example demonstrates several methods of the Queue<(Of <(T>)>) generic class. The
code example creates a queue of strings with default capacity and uses the Enqueue method to queue five
strings. The elements of the queue are enumerated, which does not change the state of the queue. The
Dequeue method is used to dequeue the first string. The Peek method is used to look at the next item in the
queue, and then the Dequeue method is used to dequeue it.

The ToArray method is used to create an array and copy the queue elements to it, then the array is passed to
the Queue<(Of <(T>)>) constructor that takes IEnumerable<(Of <(T>)>), creating a copy of the queue. The
elements of the copy are displayed.

An array twice the size of the queue is created, and the CopyTo method is used to copy the array elements
beginning at the middle of the array. The Queue<(Of <(T>)>) constructor is used again to create a second
copy of the queue containing three null elements at the beginning.

The Contains method is used to show that the string "four" is in the first copy of the queue, after which the
Clear method clears the copy and the Count property shows that the queue is empty.

Visual Basic
Imports System
Imports System.Collections.Generic

Module Example

Sub Main

Dim numbers As New Queue(Of String)


numbers.Enqueue("one")
numbers.Enqueue("two")
numbers.Enqueue("three")
numbers.Enqueue("four")
numbers.Enqueue("five")

' A queue can be enumerated without disturbing its contents.


For Each number As String In numbers
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "Dequeuing '{0}'", numbers.Dequeue())


Console.WriteLine("Peek at next item to dequeue: {0}", _
numbers.Peek())
Console.WriteLine("Dequeuing '{0}'", numbers.Dequeue())

' Create a copy of the queue, using the ToArray method and the
' constructor that accepts an IEnumerable(Of T).
Dim queueCopy As New Queue(Of String)(numbers.ToArray())

Console.WriteLine(vbLf & "Contents of the first copy:")


For Each number As String In queueCopy
Console.WriteLine(number)
Next

' Create an array twice the size of the queue, compensating


' for the fact that Visual Basic allocates an extra array
' element. Copy the elements of the queue, starting at the
' middle of the array.
Dim array2((numbers.Count * 2) - 1) As String
numbers.CopyTo(array2, numbers.Count)

' Create a second queue, using the constructor that accepts an


' IEnumerable(Of T).
Dim queueCopy2 As New Queue(Of String)(array2)

Console.WriteLine(vbLf & _
"Contents of the second copy, with duplicates and nulls:")
For Each number As String In queueCopy2
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "queueCopy.Contains(""four"") = {0}", _


queueCopy.Contains("four"))

Console.WriteLine(vbLf & "queueCopy.Clear()")


queueCopy.Clear()
Console.WriteLine(vbLf & "queueCopy.Count = {0}", _
queueCopy.Count)
End Sub
End Module

' This code example produces the following output:


'
'one
'two
'three
'four
'five
'
'Dequeuing 'one'
'Peek at next item to dequeue: two
'
'Dequeuing 'two'
'
'Contents of the copy:
'three
'four
'five
'
'Contents of the second copy, with duplicates and nulls:
'
'
'
'three
'four
'five
'
'queueCopy.Contains("four") = True
'
'queueCopy.Clear()
'
'queueCopy.Count = 0

C#
using System;
using System.Collections.Generic;

class Example
{
public static void Main()
{
Queue<string> numbers = new Queue<string>();
numbers.Enqueue("one");
numbers.Enqueue("two");
numbers.Enqueue("three");
numbers.Enqueue("four");
numbers.Enqueue("five");

// A queue can be enumerated without disturbing its contents.


foreach( string number in numbers )
{
Console.WriteLine(number);
}

Console.WriteLine("\nDequeuing '{0}'", numbers.Dequeue());


Console.WriteLine("Peek at next item to dequeue: {0}",
numbers.Peek());
Console.WriteLine("Dequeuing '{0}'", numbers.Dequeue());

// Create a copy of the queue, using the ToArray method and the
// constructor that accepts an IEnumerable<T>.
Queue<string> queueCopy = new Queue<string>(numbers.ToArray());

Console.WriteLine("\nContents of the first copy:");


foreach( string number in queueCopy )
{
Console.WriteLine(number);
}

// Create an array twice the size of the queue and copy the
// elements of the queue, starting at the middle of the
// array.
string[] array2 = new string[numbers.Count * 2];
numbers.CopyTo(array2, numbers.Count);

// Create a second queue, using the constructor that accepts an


// IEnumerable(Of T).
Queue<string> queueCopy2 = new Queue<string>(array2);

Console.WriteLine("\nContents of the second copy, with duplicates and nulls:");


foreach( string number in queueCopy2 )
{
Console.WriteLine(number);
}

Console.WriteLine("\nqueueCopy.Contains(\"four\") = {0}",
queueCopy.Contains("four"));

Console.WriteLine("\nqueueCopy.Clear()");
queueCopy.Clear();
Console.WriteLine("\nqueueCopy.Count = {0}", queueCopy.Count);
}
}

/* This code example produces the following output:

one
two
three
four
five

Dequeuing 'one'
Peek at next item to dequeue: two
Dequeuing 'two'

Contents of the copy:


three
four
five

Contents of the second copy, with duplicates and nulls:

three
four
five

queueCopy.Contains("four") = True

queueCopy.Clear()

queueCopy.Count = 0
*/
Inheritance Hierarchy
System..::.Object
System.Collections.Generic..::.Queue<(Of <(T>)>)

Thread Safety
Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not
guaranteed to be thread safe.
A Queue<(Of <(T>)>) can support multiple readers concurrently, as long as the collection is not modified.
Even so, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread
safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection
to be accessed by multiple threads for reading and writing, you must implement your own synchronization.

Queue<(Of <(T>)>)..::.GetEnumerator Method

Returns an enumerator that iterates through the Queue<(Of <(T>)>).

Namespace: System.Collections.Generic
Assembly: System (in System.dll)
Syntax
Visual Basic (Declaration)
Public Function GetEnumerator As Queue<(Of <(T>)>)..::.Enumerator
Visual Basic (Usage)
Dim instance As Queue
Dim returnValue As Queue<(Of <(T>)>)..::.Enumerator

returnValue = instance.GetEnumerator()
C#
public Queue<(Of <(T>)>)..::.Enumerator GetEnumerator()

Return Value
Type: System.Collections.Generic..::.Queue<(Of <(T>)>)..::.Enumerator
An Queue<(Of <(T>)>)..::.Enumerator for the Queue<(Of <(T>)>).

Remarks
The foreach statement of the C# language (for each in C++, For Each in Visual Basic) hides the complexity of
the enumerators. Therefore, using foreach is recommended, instead of directly manipulating the enumerator.

Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying
collection.

Initially, the enumerator is positioned before the first element in the collection. At this position, Current is
undefined. Therefore, you must call MoveNext to advance the enumerator to the first element of the collection
before reading the value of Current.

Current returns the same object until MoveNext is called. MoveNext sets Current to the next element.

If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the
collection and MoveNext returns false. When the enumerator is at this position, subsequent calls to MoveNext
also return false. If the last call to MoveNext returned false, Current is undefined. You cannot set Current to
the first element of the collection again; you must create a new enumerator instance instead.

An enumerator remains valid as long as the collection remains unchanged. If changes are made to the
collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its
behavior is undefined.

The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection
is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the
collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading
and writing, you must implement your own synchronization.

Default implementations of collections in System.Collections.Generic are not synchronized.

This method is an O(1) operation.

Examples
The following code example demonstrates that the Queue<(Of <(T>)>) generic class is enumerable. The
foreach statement (For Each in Visual Basic, for each in C++) is used to enumerate the queue.

The code example creates a queue of strings with default capacity and uses the Enqueue method to queue
five strings. The elements of the queue are enumerated, which does not change the state of the queue. The
Dequeue method is used to dequeue the first string. The Peek method is used to look at the next item in the
queue, and then the Dequeue method is used to dequeue it.

The ToArray method is used to create an array and copy the queue elements to it, then the array is passed to
the Queue<(Of <(T>)>) constructor that takes IEnumerable<(Of <(T>)>), creating a copy of the queue. The
elements of the copy are displayed.

An array twice the size of the queue is created, and the CopyTo method is used to copy the array elements
beginning at the middle of the array. The Queue<(Of <(T>)>) constructor is used again to create a second
copy of the queue containing three null elements at the beginning.

The Contains method is used to show that the string "four" is in the first copy of the queue, after which the
Clear method clears the copy and the Count property shows that the queue is empty.

Visual Basic Copy Code


Imports System
Imports System.Collections.Generic

Module Example

Sub Main

Dim numbers As New Queue(Of String)


numbers.Enqueue("one")
numbers.Enqueue("two")
numbers.Enqueue("three")
numbers.Enqueue("four")
numbers.Enqueue("five")

' A queue can be enumerated without disturbing its contents.


For Each number As String In numbers
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "Dequeuing '{0}'", numbers.Dequeue())


Console.WriteLine("Peek at next item to dequeue: {0}", _
numbers.Peek())
Console.WriteLine("Dequeuing '{0}'", numbers.Dequeue())

' Create a copy of the queue, using the ToArray method and the
' constructor that accepts an IEnumerable(Of T).
Dim queueCopy As New Queue(Of String)(numbers.ToArray())

Console.WriteLine(vbLf & "Contents of the first copy:")


For Each number As String In queueCopy
Console.WriteLine(number)
Next

' Create an array twice the size of the queue, compensating


' for the fact that Visual Basic allocates an extra array
' element. Copy the elements of the queue, starting at the
' middle of the array.
Dim array2((numbers.Count * 2) - 1) As String
numbers.CopyTo(array2, numbers.Count)

' Create a second queue, using the constructor that accepts an


' IEnumerable(Of T).
Dim queueCopy2 As New Queue(Of String)(array2)

Console.WriteLine(vbLf & _
"Contents of the second copy, with duplicates and nulls:")
For Each number As String In queueCopy2
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "queueCopy.Contains(""four"") = {0}", _


queueCopy.Contains("four"))

Console.WriteLine(vbLf & "queueCopy.Clear()")


queueCopy.Clear()
Console.WriteLine(vbLf & "queueCopy.Count = {0}", _
queueCopy.Count)
End Sub
End Module

' This code example produces the following output:


'
'one
'two
'three
'four
'five
'
'Dequeuing 'one'
'Peek at next item to dequeue: two
'
'Dequeuing 'two'
'
'Contents of the copy:
'three
'four
'five
'
'Contents of the second copy, with duplicates and nulls:
'
'
'
'three
'four
'five
'
'queueCopy.Contains("four") = True
'
'queueCopy.Clear()
'
'queueCopy.Count = 0

C#
using System;
using System.Collections.Generic;

class Example
{
public static void Main()
{
Queue<string> numbers = new Queue<string>();
numbers.Enqueue("one");
numbers.Enqueue("two");
numbers.Enqueue("three");
numbers.Enqueue("four");
numbers.Enqueue("five");

// A queue can be enumerated without disturbing its contents.


foreach( string number in numbers )
{
Console.WriteLine(number);
}

Console.WriteLine("\nDequeuing '{0}'", numbers.Dequeue());


Console.WriteLine("Peek at next item to dequeue: {0}",
numbers.Peek());
Console.WriteLine("Dequeuing '{0}'", numbers.Dequeue());

// Create a copy of the queue, using the ToArray method and the
// constructor that accepts an IEnumerable<T>.
Queue<string> queueCopy = new Queue<string>(numbers.ToArray());

Console.WriteLine("\nContents of the first copy:");


foreach( string number in queueCopy )
{
Console.WriteLine(number);
}

// Create an array twice the size of the queue and copy the
// elements of the queue, starting at the middle of the
// array.
string[] array2 = new string[numbers.Count * 2];
numbers.CopyTo(array2, numbers.Count);

// Create a second queue, using the constructor that accepts an


// IEnumerable(Of T).
Queue<string> queueCopy2 = new Queue<string>(array2);

Console.WriteLine("\nContents of the second copy, with duplicates and nulls:");


foreach( string number in queueCopy2 )
{
Console.WriteLine(number);
}
Console.WriteLine("\nqueueCopy.Contains(\"four\") = {0}",
queueCopy.Contains("four"));

Console.WriteLine("\nqueueCopy.Clear()");
queueCopy.Clear();
Console.WriteLine("\nqueueCopy.Count = {0}", queueCopy.Count);
}
}

/* This code example produces the following output:

one
two
three
four
five

Dequeuing 'one'
Peek at next item to dequeue: two
Dequeuing 'two'

Contents of the copy:


three
four
five

Contents of the second copy, with duplicates and nulls:

three
four
five

queueCopy.Contains("four") = True

queueCopy.Clear()

queueCopy.Count = 0
*/

Generic Stack

LIFO
The Stack class allows the implementation of a LIFO(Last-In-First-Out) storage system.
Due to Stack being a collection it can easily be simulated using a List. This is handy to remember so that if
find yourself trying to implement such a system just remember that one already exists!

Generic.Stack vs Stack
The Collections.Generic.Stack should always be chosen over the Collections.Stack class to promote type
safety. However, their basic operation is identical in every area apart from when using an enumerator.

Usage of Generic Stack


System.InvalidOperationException thrown if no check for within bounds.

byte data = 42;


Stack<byte> myStack = new Stack<byte>();

myStack.Push(data);

if (myStack.Count > 0) //Check within bounds


{
data = myStack.Pop();
}[edit]Simulation of Generic Stack using Generic List
Note that by simulating a stack like this means that all elements are open for access and therefore the stack
can be abused.

System.ArgumentOutOfRangeException thrown if no check for within bounds

byte data = 42;


List<byte> myList = new List<byte>();

myList.Insert(0, data); //PUSH

if (myList.Count > 0) //Check within bounds


{
//POP
data = myList[0];
myList.RemoveAt(0);
}[edit]Enumerator
The Enumerator or more precisely the Stack<T>.Enumerator allows simple iteration through the elements of
the stack.

Note: To protect the stack from abuse the enumerator only allows read operations.
Unlike the IEnumerator (returned by Collections.Stack) the Stack<T>.Enumerator does not provide a Reset
method.

The most important thing to remember when using an enumerator is not to modify the stack once an instance
of the enumerator has been created. Therefore the fool-proof way of ensuring this is to stick it inside its own
method.

using System;
using System.Collections.Generic;

static void stackEnumeratorEG()


{
Stack<byte> myStack = new Stack<byte>();

myStack.Push(1);
myStack.Push(2);
myStack.Push(3);
myStack.Push(4);
stackPrint(myStack);

myStack.Pop();
myStack.Pop();

stackPrint(myStack);
}

static void stackPrint(Stack<byte> myStack)


{
Stack<byte>.Enumerator msEnumerator = myStack.GetEnumerator();

while (msEnumerator.MoveNext())
{
Console.WriteLine(msEnumerator.Current.ToString());
}
Console.WriteLine();
}The alternative is to use a foreach statement which uses the enumerator behind the scenes.

Stack<(Of <(T>)>) Class

Represents a variable size last-in-first-out (LIFO) collection of instances of the same arbitrary type.

Namespace: System.Collections.Generic
Assembly: System (in System.dll)
Syntax
Visual Basic (Declaration)
<SerializableAttribute> _
<ComVisibleAttribute(False)> _
Public Class Stack(Of T) _
Implements IEnumerable(Of T), ICollection, IEnumerable
Visual Basic (Usage)
Dim instance As Stack(Of T)
C#
[SerializableAttribute]
[ComVisibleAttribute(false)]
public class Stack<T> : IEnumerable<T>, ICollection,
IEnumerable

Type Parameters
T
Specifies the type of elements in the stack.

Remarks
Stack<(Of <(T>)>) is implemented as an array.

The capacity of a Stack<(Of <(T>)>) is the number of elements the Stack<(Of <(T>)>) can hold. As
elements are added to a Stack<(Of <(T>)>), the capacity is automatically increased as required by
reallocating the internal array. The capacity can be decreased by calling TrimExcess.

If Count is less than the capacity of the stack, Push is an O(1) operation. If the capacity needs to be increased
to accommodate the new element, Push becomes an O(n) operation, where n is Count. Pop is an O(1)
operation.

Stack<(Of <(T>)>) accepts nullNothingnullptra null reference (Nothing in Visual Basic) as a valid value for
reference types and allows duplicate elements.
Examples
The following code example demonstrates several methods of the Stack<(Of <(T>)>) generic class. The code
example creates a stack of strings with default capacity and uses the Push method to push five strings onto
the stack. The elements of the stack are enumerated, which does not change the state of the stack. The Pop
method is used to pop the first string off the stack. The Peek method is used to look at the next item on the
stack, and then the Pop method is used to pop it off.

The ToArray method is used to create an array and copy the stack elements to it, then the array is passed to
the Stack<(Of <(T>)>) constructor that takes IEnumerable<(Of <(T>)>), creating a copy of the stack with
the order of the elements reversed. The elements of the copy are displayed.

An array twice the size of the stack is created, and the CopyTo method is used to copy the array elements
beginning at the middle of the array. The Stack<(Of <(T>)>) constructor is used again to create a copy of the
stack with the order of elements reversed; thus, the three null elements are at the end.

The Contains method is used to show that the string "four" is in the first copy of the stack, after which the
Clear method clears the copy and the Count property shows that the stack is empty.

Visual Basic Copy Code


Imports System
Imports System.Collections.Generic

Module Example

Sub Main

Dim numbers As New Stack(Of String)


numbers.Push("one")
numbers.Push("two")
numbers.Push("three")
numbers.Push("four")
numbers.Push("five")

' A stack can be enumerated without disturbing its contents.


For Each number As String In numbers
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "Popping '{0}'", numbers.Pop())


Console.WriteLine("Peek at next item to pop: {0}", _
numbers.Peek())
Console.WriteLine("Popping '{0}'", numbers.Pop())

' Create another stack, using the ToArray method and the
' constructor that accepts an IEnumerable(Of T). Note that
' the order of items on the new stack is reversed.
Dim stack2 As New Stack(Of String)(numbers.ToArray())

Console.WriteLine(vbLf & "Contents of the first copy:")


For Each number As String In stack2
Console.WriteLine(number)
Next

' Create an array twice the size of the stack, compensating


' for the fact that Visual Basic allocates an extra array
' element. Copy the elements of the stack, starting at the
' middle of the array.
Dim array2((numbers.Count * 2) - 1) As String
numbers.CopyTo(array2, numbers.Count)

' Create a second stack, using the constructor that accepts an


' IEnumerable(Of T). The elements are reversed, with the null
' elements appearing at the end of the stack when enumerated.
Dim stack3 As New Stack(Of String)(array2)

Console.WriteLine(vbLf & _
"Contents of the second copy, with duplicates and nulls:")
For Each number As String In stack3
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "stack2.Contains(""four"") = {0}", _


stack2.Contains("four"))

Console.WriteLine(vbLf & "stack2.Clear()")


stack2.Clear()
Console.WriteLine(vbLf & "stack2.Count = {0}", _
stack2.Count)
End Sub
End Module

' This code example produces the following output:


'
'five
'four
'three
'two
'one
'
'Popping 'five'
'Peek at next item to pop: four
'Popping 'four'
'
'Contents of the first copy:
'one
'two
'three
'
'Contents of the second copy, with duplicates and nulls:
'one
'two
'three
'
'
'
'
'stack2.Contains("four") = False
'
'stack2.Clear()
'
'stack2.Count = 0

C#
using System;
using System.Collections.Generic;

class Example
{
public static void Main()
{
Stack<string> numbers = new Stack<string>();
numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");

// A stack can be enumerated without disturbing its contents.


foreach( string number in numbers )
{
Console.WriteLine(number);
}

Console.WriteLine("\nPopping '{0}'", numbers.Pop());


Console.WriteLine("Peek at next item to destack: {0}",
numbers.Peek());
Console.WriteLine("Popping '{0}'", numbers.Pop());

// Create a copy of the stack, using the ToArray method and the
// constructor that accepts an IEnumerable<T>.
Stack<string> stack2 = new Stack<string>(numbers.ToArray());

Console.WriteLine("\nContents of the first copy:");


foreach( string number in stack2 )
{
Console.WriteLine(number);
}

// Create an array twice the size of the stack and copy the
// elements of the stack, starting at the middle of the
// array.
string[] array2 = new string[numbers.Count * 2];
numbers.CopyTo(array2, numbers.Count);

// Create a second stack, using the constructor that accepts an


// IEnumerable(Of T).
Stack<string> stack3 = new Stack<string>(array2);

Console.WriteLine("\nContents of the second copy, with duplicates and nulls:");


foreach( string number in stack3 )
{
Console.WriteLine(number);
}

Console.WriteLine("\nstack2.Contains(\"four\") = {0}",
stack2.Contains("four"));

Console.WriteLine("\nstack2.Clear()");
stack2.Clear();
Console.WriteLine("\nstack2.Count = {0}", stack2.Count);
}
}

/* This code example produces the following output:

five
four
three
two
one

Popping 'five'
Peek at next item to destack: four
Popping 'four'

Contents of the first copy:


one
two
three

Contents of the second copy, with duplicates and nulls:


one
two
three

stack2.Contains("four") = False

stack2.Clear()

stack2.Count = 0
*/

Inheritance Hierarchy
System..::.Object
System.Collections.Generic..::.Stack<(Of <(T>)>)

Thread Safety
Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not
guaranteed to be thread safe.

A Stack<(Of <(T>)>) can support multiple readers concurrently, as long as the collection is not modified.
Even so, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread
safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection
to be accessed by multiple threads for reading and writing, you must implement your own synchronization.

Stack<(Of <(T>)>)..::.GetEnumerator Method

Returns an enumerator for the Stack<(Of <(T>)>).

Namespace: System.Collections.Generic
Assembly: System (in System.dll)
Syntax
Visual Basic (Declaration)
Public Function GetEnumerator As Stack<(Of <(T>)>)..::.Enumerator
Visual Basic (Usage)
Dim instance As Stack
Dim returnValue As Stack<(Of <(T>)>)..::.Enumerator

returnValue = instance.GetEnumerator()
C#
public Stack<(Of <(T>)>)..::.Enumerator GetEnumerator()

Return Value
Type: System.Collections.Generic..::.Stack<(Of <(T>)>)..::.Enumerator
An Stack<(Of <(T>)>)..::.Enumerator for the Stack<(Of <(T>)>).

Remarks
The foreach statement of the C# language (for each in C++, For Each in Visual Basic) hides the complexity of
the enumerators. Therefore, using foreach is recommended, instead of directly manipulating the enumerator.

Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying
collection.

Initially, the enumerator is positioned before the first element in the collection. At this position, Current is
undefined. Therefore, you must call MoveNext to advance the enumerator to the first element of the collection
before reading the value of Current.

Current returns the same object until MoveNext is called. MoveNext sets Current to the next element.

If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the
collection and MoveNext returns false. When the enumerator is at this position, subsequent calls to MoveNext
also return false. If the last call to MoveNext returned false, Current is undefined. You cannot set Current to
the first element of the collection again; you must create a new enumerator instance instead.

An enumerator remains valid as long as the collection remains unchanged. If changes are made to the
collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its
behavior is undefined.

The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection
is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the
collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading
and writing, you must implement your own synchronization.

Default implementations of collections in System.Collections.Generic are not synchronized.

This method is an O(1) operation.

Examples
The following code example demonstrates that the Stack<(Of <(T>)>) generic class is enumerable. The
foreach statement (For Each in Visual Basic, for each in C++) is used to enumerate the queue.

The code example creates a stack of strings with default capacity and uses the Push method to push five
strings onto the stack. The elements of the stack are enumerated, which does not change the state of the
stack. The Pop method is used to pop the first string off the stack. The Peek method is used to look at the
next item on the stack, and then the Pop method is used to pop it off.

The ToArray method is used to create an array and copy the stack elements to it, then the array is passed to
the Stack<(Of <(T>)>) constructor that takes IEnumerable<(Of <(T>)>), creating a copy of the stack with
the order of the elements reversed. The elements of the copy are displayed.
An array twice the size of the stack is created, and the CopyTo method is used to copy the array elements
beginning at the middle of the array. The Stack<(Of <(T>)>) constructor is used again to create a copy of the
stack with the order of elements reversed; thus, the three null elements are at the end.

The Contains method is used to show that the string "four" is in the first copy of the stack, after which the
Clear method clears the copy and the Count property shows that the stack is empty.

Visual Basic Copy Code


Imports System
Imports System.Collections.Generic

Module Example

Sub Main

Dim numbers As New Stack(Of String)


numbers.Push("one")
numbers.Push("two")
numbers.Push("three")
numbers.Push("four")
numbers.Push("five")

' A stack can be enumerated without disturbing its contents.


For Each number As String In numbers
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "Popping '{0}'", numbers.Pop())


Console.WriteLine("Peek at next item to pop: {0}", _
numbers.Peek())
Console.WriteLine("Popping '{0}'", numbers.Pop())

' Create another stack, using the ToArray method and the
' constructor that accepts an IEnumerable(Of T). Note that
' the order of items on the new stack is reversed.
Dim stack2 As New Stack(Of String)(numbers.ToArray())

Console.WriteLine(vbLf & "Contents of the first copy:")


For Each number As String In stack2
Console.WriteLine(number)
Next

' Create an array twice the size of the stack, compensating


' for the fact that Visual Basic allocates an extra array
' element. Copy the elements of the stack, starting at the
' middle of the array.
Dim array2((numbers.Count * 2) - 1) As String
numbers.CopyTo(array2, numbers.Count)

' Create a second stack, using the constructor that accepts an


' IEnumerable(Of T). The elements are reversed, with the null
' elements appearing at the end of the stack when enumerated.
Dim stack3 As New Stack(Of String)(array2)

Console.WriteLine(vbLf & _
"Contents of the second copy, with duplicates and nulls:")
For Each number As String In stack3
Console.WriteLine(number)
Next

Console.WriteLine(vbLf & "stack2.Contains(""four"") = {0}", _


stack2.Contains("four"))

Console.WriteLine(vbLf & "stack2.Clear()")


stack2.Clear()
Console.WriteLine(vbLf & "stack2.Count = {0}", _
stack2.Count)
End Sub
End Module

' This code example produces the following output:


'
'five
'four
'three
'two
'one
'
'Popping 'five'
'Peek at next item to pop: four
'Popping 'four'
'
'Contents of the first copy:
'one
'two
'three
'
'Contents of the second copy, with duplicates and nulls:
'one
'two
'three
'
'
'
'
'stack2.Contains("four") = False
'
'stack2.Clear()
'
'stack2.Count = 0

C#
using System;
using System.Collections.Generic;

class Example
{
public static void Main()
{
Stack<string> numbers = new Stack<string>();
numbers.Push("one");
numbers.Push("two");
numbers.Push("three");
numbers.Push("four");
numbers.Push("five");

// A stack can be enumerated without disturbing its contents.


foreach( string number in numbers )
{
Console.WriteLine(number);
}

Console.WriteLine("\nPopping '{0}'", numbers.Pop());


Console.WriteLine("Peek at next item to destack: {0}",
numbers.Peek());
Console.WriteLine("Popping '{0}'", numbers.Pop());

// Create a copy of the stack, using the ToArray method and the
// constructor that accepts an IEnumerable<T>.
Stack<string> stack2 = new Stack<string>(numbers.ToArray());

Console.WriteLine("\nContents of the first copy:");


foreach( string number in stack2 )
{
Console.WriteLine(number);
}

// Create an array twice the size of the stack and copy the
// elements of the stack, starting at the middle of the
// array.
string[] array2 = new string[numbers.Count * 2];
numbers.CopyTo(array2, numbers.Count);

// Create a second stack, using the constructor that accepts an


// IEnumerable(Of T).
Stack<string> stack3 = new Stack<string>(array2);

Console.WriteLine("\nContents of the second copy, with duplicates and nulls:");


foreach( string number in stack3 )
{
Console.WriteLine(number);
}

Console.WriteLine("\nstack2.Contains(\"four\") = {0}",
stack2.Contains("four"));

Console.WriteLine("\nstack2.Clear()");
stack2.Clear();
Console.WriteLine("\nstack2.Count = {0}", stack2.Count);
}
}

/* This code example produces the following output:

five
four
three
two
one

Popping 'five'
Peek at next item to destack: four
Popping 'four'

Contents of the first copy:


one
two
three

Contents of the second copy, with duplicates and nulls:


one
two
three

stack2.Contains("four") = False

stack2.Clear()

stack2.Count = 0
*/

Generic interfaces
ICollection
IList
IDictionary
IComparable
IComparer
IEqualityComparer
IEnumerable
IEnumerator
IEnumerator<T> supports a type safe iteration over a generic collection. It has all the same members as
IEnumerator (It "inherits" from IEnumerator), however it also has a Current property of type T. The T Current
property allows retrieving the current item in the iteration without requiring a cast from object.

When implementing the generic IEnumerator, implement the nongeneric Current property explicitly:

public class MyEnumerator<T> : IEnumerator<T>{

// Implement the Generic Current implicitly


// so it is always visible
public T Current {
get{
//...
}
}

// Implement the nonGeneric Current explicitly


// so it is only visible with a
// nongeneric IEnumertor refererence
public object IEnumator.Current {
get{
//...
}
}

//...

}
Generic types

Generics is the implementation of parametric polymorphism. Using parametric polymorphism, a method or


data type can be written generically so that it can deal equally well with objects of various types. It is a way
to make a language more expressible, while still maintaining full static type-safety.

Why use generics?


There are mainly two reasons to use generics. These are:

Performance – Collections that store objects use Boxing and Unboxing on data types. This uses a significant
amount of overhead, which can give a performance hit. By using generics instead, this performance hit is
removed.
Type Safety – There is no strong type information at compile type as to what is stored in the collection.
To understand these better, a simple example which does not use generics can be used. Consider the
following class;

public class Stack


{
object[] store;
int size;
public void Push(object obj) {...}
public object Pop() {...}
}In order to use this class you can push any object onto the Stack, however when retrieving an object, an
explicit cast is required.

Stack s = new Stack();


s.Push(28);
int j = (int)s.Pop(); //unboxing with explicit int casting Such Boxing and Unboxing operations add
performance overhead since they involve dynamic memory allocations and run-time type checks.

Now imagine what would happen if you pushed a string on the Stack as in the following code;

Stack s = new Stack();


s.Push("Hello World!"); // pushing the string
int i = (int)s.Pop(); // run-time exception will be thrown at this point The code will compile, however the
problem will not become visible until the code is executed, at which point an InvalidCastException will be
thrown.

Generic equivalent
If the Stack class above was of a generic type, there would be a compile-time error when pushing the string
onto the Stack. The generic version of the Stack class looks like the following code;

public class Stack<T>


{
// Items are of type T, which is known when you create the object
T[] items;
int count;
public void Push(T item) {...}
// The type of the method Pop will be decided when you create the object
public T Pop() {...}
}T is the type for the parameter. Within class you can use T as if it were a type, this could be anything from a
simple data-type such as int to a complex object such as Car.

In the following example, string is given as the type argument for T:

Stack<string> s = new Stack<string>();


s.Push("Hello World!");
string str = s.Pop();The Stack<string> type is called a constructed type. In the Stack<string> type, every
occurrence of T is replaced with the type argument string. The Push and Pop methods of a Stack<string>
operate on string values, making it a compile-time error to push values of other types onto the Stack, and
eliminating the need to explicitly cast values back to their original type when they are retrieved.

You can use parameterization not only for classes but also for interfaces, structs, methods and delegates.

interface IComparable <T>

struct HashBucket <K,D>

static void Sort <T> (T[] arr)

delegate void Action <T> (T arg)

Terminology
There are several terms that are used when talking about generics, so it is worth mentioning them here so
that when reading other documents, a better understanding can be obtained.

Type parameters
A type parameter refers to the parameter that is used in the definition of the generic type. In the generic
version of the Stack class above, the class accepts one type parameter, T.

Type arguments
A type argument refers to the type you specify to use in place of the type parameter. In the following code
segment, string is the type argument.

Stack<string> s = new Stack<string>();[edit]Open types


Instead of referring to this as a class, generics consider the Stack<T> as an "open type". The term "open" is
meant to convey the idea that the type is not fully defined and is "open" to taking on multiple real
representations.

Constructed types
A constructed type represents an instance of an open type. To create a constructed type from the open Stack
type, use the following code:

Stack<string> s;Or

Stack<string> s = new Stack<string>();[edit]Open constructed type


An open constructed type is created when at least one type argument is left unspecified, the parameter is still
open to run-time definition. Consider the following type declaration:

public class LinkedList<K,T> { ... }The following are all open constructed types:

LinkedList<K,T> myList_1;
LinkedList<int,T> myList_2;
LinkedList<K,string> myList_3;[edit]Closed constructed type
A closed constructed type is created by specifying all of the type arguments, therefore they are not open to
run-time definition. Consider the following type declaration:

public class LinkedList<K,T> { ... }The following are all closed constructed types:

LinkedList<int,string> myList_1;
LinkedList<int,object> myList_2;
LinkedList<object,string> myList_3;

Constraints on type parameters


Constraints are used to restrict a generic class to the kinds of types that client code can use for type
arguments. If code attempts to instantiate the class with a type that is not allowed by a constraint, then this
will result in a compile-time error. Constraints are specified using the where keyword. The following table lists
the five types of constraints:

Constraint Description
where T : struct The type argument, T, must be any value type except Nullable.
where T : class The type argument, T, must be a reference type, including any class, interface, delegate, or
array type.
where T : new() The type argument, T, must have a public no-argument constructor. When used in
conjunction with other constraints, the new() constraint must be specified last.
where T : <base class name> The type argument, T, must be or derive from the specified base class.
where T : <interface name> The type argument, T, must be or implement the specified interface. Multiple
interface constraints can be specified. The constraining interface can also be generic.
where T : U The type argument, T, must be or derive from the argument supplied for U. This is called a
naked type constraint.

Generic classes
Generic classes encapsulate operations that are not specific to a particular data type. Generic classes can be
the base class to other classes, and can therefore define any number of virtual or abstract methods. Any
derived type must abide by rules to ensure that the nature of the generic abstraction flows through to it.

If a non-generic class extends a generic class, the derived class must specify a type parameter:
// Generic list class.
public class GenericList<T>
{
private List<T> myList = new List<T>();
}

// Derived type specifies the type parameter.


public class MyStringList : GenericList<string>
{
}If a generic base class defines generic virtual or abstract methods, the derived type must override the
generic methods using the specified type parameter:
// Generic class with virtual method.
public class GenericList<T>
{
private List<T> myList = new List<T>();

public virtual void PrintList(T data)


{
}
}

public class MyStringList : GenericList<string>


{
// Derived method must substitute the type parameter
public override void PrintList(string data)
{
}
}A generic derived type may reuse the type placeholder in its definition. Any constraints placed on the base
class must be honoured by the derived type:
// Default constructor constraint.
public class GenericList<T> where T : new()
{
private List<T> myList = new List<T>();
public virtual void PrintList(T data)
{
}
}

// Derived type must honour constraint.


public class MyReadOnlyList<T> : GenericList<T> where T : new()
{
public override void PrintList(T data)
{
}
}

Generic interfaces
With generic classes it is preferable to use generic interfaces, such as IComparable<T> rather than
IComparable, in order to avoid Boxing and Unboxing operations on value types. When an interface is specified
as a constraint on a type parameter, only types that implement the interface can be used. For example:

public class SortedList<T> : GenericList<T> where T : System.IComparable<T>


{
...
}
Defining a generic interface
You may define generic interfaces similar to generic classes (including constraints):

// Standard Interface
public interface IPrint
{
void Print();
}

// Generic Interface
public interface MyGenericInterface<T> where T : IPrint
{
void Run(T t);
}

// Class that implements standard Interface


public class MyPrinter : IPrint
{
public void Print()
{
Console.WriteLine("hello");
}
}

// Class that implements Generic Interface


public class Print2 : MyGenericInterface<MyPrinter>
{
public void Run(MyPrinter t)
{
t.Print();
}
}

// Generic Class that implements Generic Interface with contraints


public class PrintDemo<T> : MyGenericInterface<T> where T : IPrint
{
public void Run(T t)
{
t.Print();
}
}The .NET Framework has generic versions of all of the common interfaces.

Generic delegates
Suppose that we want a delegate that can update an item, but we are not sure what item is going to be
updated. In this scenario, making the delegate generic is the best option. In order to explain this concept, the
following code is based on an example from Tod Golding in .Net 2.0 Generics.

Imagine if you will that we are creating a piece of software that works with animals, namely cats and dogs. So
here are two classes with some properties and a ToString() method:

public class Cat


{
private string m_name;
public string Name
{
get { return m_name; }
set { m_name = value; }
}

private int m_age;


public int Age
{
get { return m_age; }
set { m_age = value; }
}

public Cat(string name, int age)


{
m_name = name;
m_age = age;
}

public override string ToString()


{
return string.Format("The Cat named {0} is {1} years old",
m_name.ToString(), m_age.ToString());
}
}

public class Dog


{
private string m_name;
public string Name
{
get { return m_name; }
set { m_name = value; }
}

private double m_age;


public double Age
{
get { return m_age; }
set { m_age = value; }
}

public Dog(string name, double age)


{
m_name = name;
m_age = age;
}

public override string ToString()


{
return string.Format("The Dog named {0} is {1} years old",
m_name.ToString(), m_age.ToString());
}
}We want a delegate that can update the age of either a cat or a dog.

public delegate void UpdateAnimal<T>(T value);As we will have many animals, a collection would be a good
thing to have, and again to save on overhead and to give type safety, a generic collection would be best.

public class Animals<T> : List<T>


{
public void UpdateAnimals(UpdateAnimal<T> updater)
{
List<T>.Enumerator items = GetEnumerator();

while (items.MoveNext())
{
updater(items.Current);
}
}

public void Print()


{
List<T>.Enumerator items = GetEnumerator();

while (items.MoveNext())
{
Console.WriteLine(items.Current.ToString());
}
}
}Finally, we need a couple of methods to be called by the delegate to update each of the classes, and some
code to test them.

class Program
{
static void Main(string[] args)
{
// Create Lists
Animals<Cat> catList = new Animals<Cat>();
catList.Add(new Cat("Tinkerbelle", 6));
catList.Add(new Cat("Felix", 3));
catList.Add(new Cat("Whiskers", 10));
catList.Add(new Cat("Tailz", 14));

Animals<Dog> dogList = new Animals<Dog>();


dogList.Add(new Dog("Rufus", 12.1));
dogList.Add(new Dog("Peeps", 3.2));
dogList.Add(new Dog("Hairy McClary", 6.3));

// Cats
catList.Print();
Console.WriteLine("---------------------------");

catList.UpdateAnimals(new UpdateAnimal<Cat>(UpdateCatAge));
catList.Print();

Console.WriteLine("===========================");

// Dogs
dogList.Print();
Console.WriteLine("---------------------------");

dogList.UpdateAnimals(new UpdateAnimal<Dog>(UpdateDogAge));
dogList.Print();
}

public static void UpdateCatAge(Cat cat)


{
cat.Age += 1;
}

public static void UpdateDogAge(Dog dog)


{
dog.Age += 0.1;
}
}
This gives the output:

Benefits of Generics

Generics provide the solution to a limitation in earlier versions of the common language runtime and the C#
language in which generalization is accomplished by casting types to and from the universal base type Object.
By creating a generic class, you can create a collection that is type-safe at compile-time.
The limitations of using non-generic collection classes can be demonstrated by writing a short program that
uses the ArrayList collection class from the .NET Framework class library. ArrayList is a highly convenient
collection class that can be used without modification to store any reference or value type.

C#
// The .NET Framework 1.1 way to create a list:
System.Collections.ArrayList list1 = new System.Collections.ArrayList();
list1.Add(3);
list1.Add(105);

System.Collections.ArrayList list2 = new System.Collections.ArrayList();


list2.Add("It is raining in Redmond.");
list2.Add("It is snowing in the mountains.");

But this convenience comes at a cost. Any reference or value type that is added to an ArrayList is implicitly
upcast to Object. If the items are value types, they must be boxed when they are added to the list, and
unboxed when they are retrieved. Both the casting and the boxing and unboxing operations decrease
performance; the effect of boxing and unboxing can be very significant in scenarios where you must iterate
over large collections.

The other limitation is lack of compile-time type checking; because an ArrayList casts everything to Object,
there is no way at compile-time to prevent client code from doing something such as this:

C#
System.Collections.ArrayList list = new System.Collections.ArrayList();
// Add an integer to the list.
list.Add(3);
// Add a string to the list. This will compile, but may cause an error later.
list.Add("It is raining in Redmond.");

int t = 0;
// This causes an InvalidCastException to be returned.
foreach (int x in list)
{
t += x;
}

Although perfectly acceptable and sometimes intentional if you are creating a heterogeneous collection,
combining strings and ints in a single ArrayList is more likely to be a programming error, and this error will
not be detected until runtime.

In versions 1.0 and 1.1 of the C# language, you could avoid the dangers of generalized code in the .NET
Framework base class library collection classes only by writing your own type specific collections. Of course,
because such a class is not reusable for more than one data type, you lose the benefits of generalization, and
you have to rewrite the class for each type that will be stored.

What ArrayList and other similar classes really need is a way for client code to specify, on a per-instance
basis, the particular data type that they intend to use. That would eliminate the need for the upcast to
T:System.Object and would also make it possible for the compiler to do type checking. In other words,
ArrayList needs a type parameter. That is exactly what generics provide. In the generic List<(Of <(T>)>)
collection, in the N:System.Collections.Generic namespace, the same operation of adding items to the
collection resembles this:

C#
// The .NET Framework 2.0 way to create a list
List<int> list1 = new List<int>();
// No boxing, no casting:
list1.Add(3);

// Compile-time error:
// list1.Add("It is raining in Redmond.");

For client code, the only added syntax with List<(Of <(T>)>) compared to ArrayList is the type argument in
the declaration and instantiation. In return for this slightly more coding complexity, you can create a list that
is not only safer than ArrayList, but also significantly faster, especially when the list items are value types.

Constraints on Type Parameters

When you define a generic class, you can apply restrictions to the kinds of types that client code can use for
type arguments when it instantiates your class. If client code tries to instantiate your class by using a type
that is not allowed by a constraint, the result is a compile-time error. These restrictions are called constraints.
Constraints are specified by using the where contextual keyword. The following table lists the six types of
constraints:

Constraint Description

where T: struct The type argument must be a value type. Any value type except Nullable can be
specified.
where T : class The type argument must be a reference type; this applies also to any class, interface,
delegate, or array type.
where T : new() The type argument must have a public parameterless constructor. When used together
with other constraints, the new() constraint must be specified last.
where T : <base class name> The type argument must be or derive from the specified base class.
where T : <interface name> The type argument must be or implement the specified interface. Multiple
interface constraints can be specified. The constraining interface can also
be generic.
where T : U The type argument supplied for T must be or derive from the argument supplied for U.
This is called a naked type constraint.
Why Use Constraints
If you want to examine an item in a generic list to determine whether it is valid or to compare it to some
other item, the compiler must have some guarantee that the operator or method it has to call will be
supported by any type argument that might be specified by client code. This guarantee is obtained by
applying one or more constraints to your generic class definition. For example, the base class constraint tells
the compiler that only objects of this type or derived from this type will be used as type arguments. Once the
compiler has this guarantee, it can allow methods of that type to be called in the generic class. Constraints
are applied by using the contextual keyword where. The following code example demonstrates the
functionality we can add to the GenericList<T> class (in Introduction to Generics (C# Programming Guide))
by applying a base class constraint.

C#
public class Employee
{
private string name;
private int id;

public Employee(string s, int i)


{
name = s;
id = i;
}

public string Name


{
get { return name; }
set { name = value; }
}

public int ID
{
get { return id; }
set { id = value; }
}
}

public class GenericList<T> where T : Employee


{
private class Node
{
private Node next;
private T data;

public Node(T t)
{
next = null;
data = t;
}

public Node Next


{
get { return next; }
set { next = value; }
}

public T Data
{
get { return data; }
set { data = value; }
}
}

private Node head;

public GenericList() //constructor


{
head = null;
}

public void AddHead(T t)


{
Node n = new Node(t);
n.Next = head;
head = n;
}

public IEnumerator<T> GetEnumerator()


{
Node current = head;

while (current != null)


{
yield return current.Data;
current = current.Next;
}
}

public T FindFirstOccurrence(string s)
{
Node current = head;
T t = null;

while (current != null)


{
//The constraint enables access to the Name property.
if (current.Data.Name == s)
{
t = current.Data;
break;
}
else
{
current = current.Next;
}
}
return t;
}
}

The constraint enables the generic class to use the Employee.Name property because all items of type T are
guaranteed to be either an Employee object or an object that inherits from Employee.

Multiple constraints can be applied to the same type parameter, and the constraints themselves can be
generic types, as follows:

C#
class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
// ...
}

By constraining the type parameter, you increase the number of allowable operations and method calls to
those supported by the constraining type and all types in its inheritance hierarchy. Therefore, when you
design generic classes or methods, if you will be performing any operation on the generic members beyond
simple assignment or calling any methods not supported by System.Object, you will have to apply constraints
to the type parameter.

When applying the where T : class constraint, avoid the == and != operators on the type parameter because
these operators will test for reference identity only, not for value equality. This is the case even if these
operators are overloaded in a type that is used as an argument. The following code illustrates this point; the
output is false even though the String class overloads the == operator.

C#
public static void OpTest<T>(T s, T t) where T : class
{
System.Console.WriteLine(s == t);
}
static void Main()
{
string s1 = "foo";
System.Text.StringBuilder sb = new System.Text.StringBuilder("foo");
string s2 = sb.ToString();
OpTest<string>(s1, s2);
}

The reason for this behavior is that, at compile time, the compiler only knows that T is a reference type, and
therefore must use the default operators that are valid for all reference types. If you must test for value
equality, the recommended way is to also apply the where T : IComparable<T> constraint and implement
that interface in any class that will be used to construct the generic class.

Constraining Multiple Parameters


You can apply constraints to multiple parameters, and multiple constraints to a single parameter, as shown in
the following example:

C#
class Base { }
class Test<T, U>
where U : struct
where T : Base, new() { }

Unbounded Type Parameters


Type parameters that have no constraints, such as T in public class SampleClass<T>{}, are called unbounded
type parameters. Unbounded type parameters have the following rules:

The != and == operators cannot be used because there is no guarantee that the concrete type argument will
support these operators.

They can be converted to and from System.Object or explicitly converted to any interface type.

You can compare to null. If an unbounded parameter is compared to null, the comparison will always return
false if the type argument is a value type.

Naked Type Constraints


When a generic type parameter is used as a constraint, it is called a naked type constraint. Naked type
constraints are useful when a member function with its own type parameter has to constrain that parameter
to the type parameter of the containing type, as shown in the following example:

C#
class List<T>
{
void Add<U>(List<U> items) where U : T {/*...*/}
}

In the previous example, T is a naked type constraint in the context of the Add method, and an unbounded
type parameter in the context of the List class.

Naked type constraints can also be used in generic class definitions. Note that the naked type constraint must
also have been declared within the angle brackets together with any other type parameters:

C#
//naked type constraint
public class SampleClass<T, U, V> where T : V { }
The usefulness of naked type constraints with generic classes is very limited because the compiler can assume
nothing about a naked type constraint except that it derives from System.Object. Use naked type constraints
on generic classes in scenarios in which you want to enforce an inheritance relationship between two type
parameters.

default Keyword in Generic Code


In generic classes and methods, one issue that arises is how to assign a default value to a parameterized type
T when you do not know the following in advance:

Whether T will be a reference type or a value type.

If T is a value type, whether it will be a numeric value or a struct.

Given a variable t of a parameterized type T, the statement t = null is only valid if T is a reference type and t
= 0 will only work for numeric value types but not for structs. The solution is to use the default keyword,
which will return null for reference types and zero for numeric value types. For structs, it will return each
member of the struct initialized to zero or null depending on whether they are value or reference types. For
nullable value types, default returns a System..::.Nullable<(Of <(T>)>), which is initialized like any struct.

The following example from the GenericList<T> class shows how to use the default keyword. For more
information, see Generics Overview.

C#
public class GenericList<T>
{
private class Node
{
//...

public Node Next;


public T Data;
}

private Node head;

//...

public T GetNext()
{
T temp = default(T);

Node current = head;


if (current != null)
{
temp = current.Data;
current = current.Next;
}
return temp;
}
}

Generics
Generics were added to version 2.0 of the C# language and the common language runtime (CLR). Generics
introduce to the .NET Framework the concept of type parameters, which make it possible to design classes
and methods that defer the specification of one or more types until the class or method is declared and
instantiated by client code. For example, by using a generic type parameter T you can write a single class that
other client code can use without incurring the cost or risk of runtime casts or boxing operations, as shown
here:

C#
// Declare the generic class.
public class GenericList<T>
{
void Add(T input) { }
}
class TestGenericList
{
private class ExampleClass { }
static void Main()
{
// Declare a list of type int.
GenericList<int> list1 = new GenericList<int>();

// Declare a list of type string.


GenericList<string> list2 = new GenericList<string>();

// Declare a list of type ExampleClass.


GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
}
}

Generics Overview
Use generic types to maximize code reuse, type safety, and performance.

The most common use of generics is to create collection classes.

The .NET Framework class library contains several new generic collection classes in the
System.Collections.Generic namespace. These should be used whenever possible instead of classes such as
ArrayList in the System.Collections namespace.

You can create your own generic interfaces, classes, methods, events and delegates.

Generic classes may be constrained to enable access to methods on particular data types.

Information on the types that are used in a generic data type may be obtained at run-time by using reflection.

Generics and Reflection

Because the Common Language Runtime (CLR) has access to generic type information at run time, you can
use reflection to obtain information about generic types in the same way as for non-generic types. For more
information, see Generics in the Run Time (C# Programming Guide).

In the .NET Framework 2.0 several new members are added to the Type class to enable run-time information
for generic types. See the documentation on these classes for more information on how to use these methods
and properties. The System.Reflection.Emit namespace also contains new members that support generics.
See How to: Define a Generic Type with Reflection Emit.

For a list of the invariant conditions for terms used in generic reflection, see the IsGenericType property
remarks.

System.Type MemberName Description

IsGenericType Returns true if a type is generic.


GetGenericArguments Returns an array of Type objects that represent the type arguments
supplied for a constructed type, or the type parameters of a generic type
definition.
GetGenericTypeDefinition Returns the underlying generic type definition for the current constructed
type.
GetGenericParameterConstraints Returns an array of Type objects that represent the constraints on the
current generic type parameter.
ContainsGenericParameters Returns true if the type or any of its enclosing types or methods contain
type parameters for which specific types have not been supplied.
GenericParameterAttributes Gets a combination of GenericParameterAttributes flags that describe the
special constraints of the current generic type parameter.
GenericParameter Position For a Type object that represents a type parameter, gets the position of the
type parameter in the type parameter list of the generic type definition or
generic method definition that declared the type parameter.
IsGenericParameter Gets a value that indicates whether the current Type represents a type parameter of a
generic type or method definition.
IsGenericTypeDefinition Gets a value that indicates whether the current Type represents a generic
type definition, from which other generic types can be constructed.
Returns true if the type represents the definition of a generic type.
DeclaringMethod Returns the generic method that defined the current generic type parameter, or null if
the type parameter was not defined by a generic method.
MakeGenericType Substitutes the elements of an array of types for the type parameters of the current
generic type definition, and returns a Type object representing the
resulting constructed type.

In addition, new members are added to the MethodInfo class to enable run-time information for generic
methods. See the IsGenericMethod property remarks for a list of invariant conditions for terms used to reflect
on generic methods.

System.Reflection.MemberInfo Member Name Description


IsGenericMethod Returns true if a method is generic.
GetGenericArguments Returns an array of Type objects that represent the type
arguments of a constructed generic method or the type
parameters of a generic method definition.
GetGenericMethodDefinition Returns the underlying generic method definition for the
current constructed method.
ContainsGenericParameters Returns true if the method or any of its enclosing types
contain any type parameters for which specific types have
not been supplied.
IsGenericMethodDefinition Returns true if the current MethodInfo represents the
definition of a generic method.
MakeGenericMethod Substitutes the elements of an array of types for the type parameters of the current
generic method definition, and returns a MethodInfo object
representing the resulting constructed method.

Generic Classes
Generic classes encapsulate operations that are not specific to a particular data type. The most common use
for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on.
Operations such as adding and removing items from the collection are performed in basically the same way
regardless of the type of data being stored.

For most scenarios that require collection classes, the recommended approach is to use the ones provided in
the .NET Framework class library. For more information about using these classes, see Generics in the .NET
Framework Class Library (C# Programming Guide).
Typically, you create generic classes by starting with an existing concrete class, and changing types into type
parameters one at a time until you reach the optimal balance of generalization and usability. When creating
your own generic classes, important considerations include the following:

Which types to generalize into type parameters.

As a rule, the more types you can parameterize, the more flexible and reusable your code becomes. However,
too much generalization can create code that is difficult for other developers to read or understand.

What constraints, if any, to apply to the type parameters (See Constraints on Type Parameters (C#
Programming Guide)).

A good rule is to apply the maximum constraints possible that will still let you handle the types you must
handle. For example, if you know that your generic class is intended for use only with reference types, apply
the class constraint. That will prevent unintended use of your class with value types, and will enable you to
use the as operator on T, and check for null values.

Whether to factor generic behavior into base classes and subclasses.

Because generic classes can serve as base classes, the same design considerations apply here as with non-
generic classes. See the rules about inheriting from generic base classes later in this topic.

Whether to implement one or more generic interfaces.

For example, if you are designing a class that will be used to create items in a generics-based collection, you
may have to implement an interface such as IComparable<(Of <(T>)>) where T is the type of your class.

For an example of a simple generic class, see Introduction to Generics (C# Programming Guide).

The rules for type parameters and constraints have several implications for generic class behavior, especially
regarding inheritance and member accessibility. Before proceeding, you should understand some terms. For a
generic class Node<T>, client code can reference the class either by specifying a type argument, to create a
closed constructed type (Node<int>). Alternatively, it can leave the type parameter unspecified, for example
when you specify a generic base class, to create an open constructed type (Node<T>). Generic classes can
inherit from concrete, closed constructed, or open constructed base classes:

C#
class BaseNode { }
class BaseNodeGeneric<T> { }

// concrete type
class NodeConcrete<T> : BaseNode { }

//closed constructed type


class NodeClosed<T> : BaseNodeGeneric<int> { }

//open constructed type


class NodeOpen<T> : BaseNodeGeneric<T> { }

Non-generic, in other words, concrete, classes can inherit from closed constructed base classes, but not from
open constructed classes or naked type parameters because there is no way at run time for client code to
supply the type argument required to instantiate the base class.

C#
//No error
class Node1 : BaseNodeGeneric<int> { }
//Generates an error
//class Node2 : BaseNodeGeneric<T> {}

//Generates an error
//class Node3 : T {}

Generic classes that inherit from open constructed types must supply type arguments for any base class type
parameters that are not shared by the inheriting class, as demonstrated in the following code:

C#
class BaseNodeMultiple<T, U> { }

//No error
class Node4<T> : BaseNodeMultiple<T, int> { }

//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }

//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {}

Generic classes that inherit from open constructed types must specify constraints that are a superset of, or
imply, the constraints on the base type:

C#
class NodeItem<T> where T : System.IComparable<T>, new() { }
class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }

Generic types can use multiple type parameters and constraints, as follows:

C#
class SuperKeyType<K, V, U>
where U : System.IComparable<U>
where V : new()
{}

Open constructed and closed constructed types can be used as method parameters:

C#
void Swap<T>(List<T> list1, List<T> list2)
{
//code to swap items
}

void Swap(List<int> list1, List<int> list2)


{
//code to swap items
}

If a generic class implements an interface, all instances of that class can be cast to that interface.
Generic classes are invariant. In other words, if an input parameter specifies a List<BaseClass>, you will get a
compile-time error if you try to provide a List<DerivedClass>.

Generic Delegates
A delegate can define its own type parameters. Code that references the generic delegate can specify the type
argument to create a closed constructed type, just like when instantiating a generic class or calling a generic
method, as shown in the following example:
C#
public delegate void Del<T>(T item);
public static void Notify(int i) { }

Del<int> m1 = new Del<int>(Notify);

C# version 2.0 has a new feature called method group conversion, which applies to concrete as well as
generic delegate types, and enables you to write the previous line with this simplified syntax:

C#
Del<int> m2 = Notify;

Delegates defined within a generic class can use the generic class type parameters in the same way that class
methods do.

C#
class Stack<T>
{
T[] items;
int index;

public delegate void StackDelegate(T[] items);


}

Code that references the delegate must specify the type argument of the containing class, as follows:

C#
private static void DoWork(float[] items) { }

public static void TestStack()


{
Stack<float> s = new Stack<float>();
Stack<float>.StackDelegate d = DoWork;
}

Generic delegates are especially useful in defining events based on the typical design pattern because the
sender argument can be strongly typed and no longer has to be cast to and from Object.

C#
delegate void StackEventHandler<T, U>(T sender, U eventArgs);

class Stack<T>
{
public class StackEventArgs : System.EventArgs { }
public event StackEventHandler<Stack<T>, StackEventArgs> stackEvent;

protected virtual void OnStackChanged(StackEventArgs a)


{
stackEvent(this, a);
}
}

class SampleClass
{
public void HandleStackChange<T>(Stack<T> stack, Stack<T>.StackEventArgs args) { }
}
public static void Test()
{
Stack<double> s = new Stack<double>();
SampleClass o = new SampleClass();
s.stackEvent += o.HandleStackChange;
}

Generic Interfaces
It is often useful to define interfaces either for generic collection classes, or for the generic classes that
represent items in the collection. The preference for generic classes is to use generic interfaces, such as
IComparable<(Of <(T>)>) rather than IComparable, in order to avoid boxing and unboxing operations on
value types. The .NET Framework class library defines several generic interfaces for use with the collection
classes in the System.Collections.Generic namespace.
When an interface is specified as a constraint on a type parameter, only types that implement the interface
can be used. The following code example shows a SortedList<T> class that derives from the GenericList<T>
class. For more information, see Introduction to Generics (C# Programming Guide). SortedList<T> adds the
constraint where T : IComparable<T>. This enables the BubbleSort method in SortedList<T> to use the
generic CompareTo method on list elements. In this example, list elements are a simple class, Person, that
implements IComparable<Person>.

C#
//Type parameter T in angle brackets.
public class GenericList<T> : System.Collections.Generic.IEnumerable<T>
{
protected Node head;
protected Node current = null;

// Nested class is also generic on T


protected class Node
{
public Node next;
private T data; //T as private member datatype

public Node(T t) //T used in non-generic constructor


{
next = null;
data = t;
}

public Node Next


{
get { return next; }
set { next = value; }
}

public T Data //T as return type of property


{
get { return data; }
set { data = value; }
}
}

public GenericList() //constructor


{
head = null;
}
public void AddHead(T t) //T as method parameter type
{
Node n = new Node(t);
n.Next = head;
head = n;
}

// Implementation of the iterator


public System.Collections.Generic.IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}

// IEnumerable<T> inherits from IEnumerable, therefore this class


// must implement both the generic and non-generic versions of
// GetEnumerator. In most cases, the non-generic method can
// simply call the generic method.
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

public class SortedList<T> : GenericList<T> where T : System.IComparable<T>


{
// A simple, unoptimized sort algorithm that
// orders list elements from lowest to highest:

public void BubbleSort()


{
if (null == head || null == head.Next)
{
return;
}
bool swapped;

do
{
Node previous = null;
Node current = head;
swapped = false;

while (current.next != null)


{
// Because we need to call this method, the SortedList
// class is constrained on IEnumerable<T>
if (current.Data.CompareTo(current.next.Data) > 0)
{
Node tmp = current.next;
current.next = current.next.next;
tmp.next = current;
if (previous == null)
{
head = tmp;
}
else
{
previous.next = tmp;
}
previous = tmp;
swapped = true;
}
else
{
previous = current;
current = current.next;
}
}
} while (swapped);
}
}

// A simple class that implements IComparable<T> using itself as the


// type argument. This is a common design pattern in objects that
// are stored in generic lists.
public class Person : System.IComparable<Person>
{
string name;
int age;

public Person(string s, int i)


{
name = s;
age = i;
}

// This will cause list elements to be sorted on age values.


public int CompareTo(Person p)
{
return age - p.age;
}

public override string ToString()


{
return name + ":" + age;
}

// Must implement Equals.


public bool Equals(Person p)
{
return (this.age == p.age);
}
}

class Program
{
static void Main()
{
//Declare and instantiate a new generic SortedList class.
//Person is the type argument.
SortedList<Person> list = new SortedList<Person>();

//Create name and age values to initialize Person objects.


string[] names = new string[]
{
"Franscoise",
"Bill",
"Li",
"Sandra",
"Gunnar",
"Alok",
"Hiroyuki",
"Maria",
"Alessandro",
"Raul"
};

int[] ages = new int[] { 45, 19, 28, 23, 18, 9, 108, 72, 30, 35 };

//Populate the list.


for (int x = 0; x < 10; x++)
{
list.AddHead(new Person(names[x], ages[x]));
}

//Print out unsorted list.


foreach (Person p in list)
{
System.Console.WriteLine(p.ToString());
}
System.Console.WriteLine("Done with unsorted list");

//Sort the list.


list.BubbleSort();

//Print out sorted list.


foreach (Person p in list)
{
System.Console.WriteLine(p.ToString());
}
System.Console.WriteLine("Done with sorted list");
}
}

Multiple interfaces can be specified as constraints on a single type, as follows:

C#
class Stack<T> where T : System.IComparable<T>, IEnumerable<T>
{
}

An interface can define more than one type parameter, as follows:

C#
interface IDictionary<K, V>
{
}

The rules of inheritance that apply to classes also apply to interfaces:

C#
interface IMonth<T> { }

interface IJanuary : IMonth<int> { } //No error


interface IFebruary<T> : IMonth<int> { } //No error
interface IMarch<T> : IMonth<T> { } //No error
//interface IApril<T> : IMonth<T, U> {} //Error

Generic interfaces can inherit from non-generic interfaces if the generic interface is contra-variant, which
means it only uses its type parameter as a return value. In the .NET Framework class library,
IEnumerable<(Of <(T>)>) inherits from IEnumerable because IEnumerable<(Of <(T>)>) only uses T in the
return value of GetEnumerator and in the Current property getter.

Concrete classes can implement closed constructed interfaces, as follows:

C#
interface IBaseInterface<T> { }

class SampleClass : IBaseInterface<string> { }

Generic classes can implement generic interfaces or closed constructed interfaces as long as the class
parameter list supplies all arguments required by the interface, as follows:

C#
interface IBaseInterface1<T> { }
interface IBaseInterface2<T, U> { }

class SampleClass1<T> : IBaseInterface1<T> { } //No error


class SampleClass2<T> : IBaseInterface2<T, string> { } //No error

The rules that control method overloading are the same for methods within generic classes, generic structs, or
generic interfaces

Generic Methods
A generic method is a method that is declared with type parameters, as follows:

C#
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}

The following code example shows one way to call the method by using int for the type argument:

C#
public static void TestSwap()
{
int a = 1;
int b = 2;

Swap<int>(ref a, ref b);


System.Console.WriteLine(a + " " + b);
}

You can also omit the type argument and the compiler will infer it. The following call to Swap is equivalent to
the previous call:

C#
Swap(ref a, ref b);

The same rules for type inference apply to static methods and instance methods. The compiler can infer the
type parameters based on the method arguments you pass in; it cannot infer the type parameters only from a
constraint or return value. Therefore type inference does not work with methods that have no parameters.
Type inference occurs at compile time before the compiler tries to resolve overloaded method signatures. The
compiler applies type inference logic to all generic methods that share the same name. In the overload
resolution step, the compiler includes only those generic methods on which type inference succeeded.
Within a generic class, non-generic methods can access the class-level type parameters, as follows:

C#
class SampleClass<T>
{
void Swap(ref T lhs, ref T rhs) { }
}

If you define a generic method that takes the same type parameters as the containing class, the compiler
generates warning CS0693 because within the method scope, the argument supplied for the inner T hides the
argument supplied for the outer T. If you require the flexibility of calling a generic class method with type
arguments other than the ones provided when the class was instantiated, consider providing another identifier
for the type parameter of the method, as shown in GenericList2<T> in the following example.

C#
class GenericList<T>
{
// CS0693
void SampleMethod<T>() { }
}

class GenericList2<T>
{
//No warning
void SampleMethod<U>() { }
}

Use constraints to enable more specialized operations on type parameters in methods. This version of
Swap<T>, now named SwapIfGreater<T>, can only be used with type arguments that implement
IComparable<(Of <(T>)>).

C#
void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
}
}

Generic methods can be overloaded on several type parameters. For example, the following methods can all
be located in the same class:

C#
void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }

Generics in the .NET Framework Class Library


Version 2.0 of the .NET Framework class library provides a new namespace, System.Collections.Generic,
which includes several ready-to-use generic collection classes and associated interfaces. Other namespaces,
such as System, also provide new generic interfaces such as IComparable<(Of <(T>)>). These classes and
interfaces are more efficient and type-safe than the non-generic collection classes provided in earlier releases
of the .NET Framework. Before designing and implementing your own custom collection classes, consider
whether you can use or derive a class from one of the classes provided in the .NET Framework class library.

Generics in the Run Time

When a generic type or method is compiled into Microsoft intermediate language (MSIL), it contains metadata
that identifies it as having type parameters. How the MSIL for a generic type is used differs based on whether
the supplied type parameter is a value type or reference type.

When a generic type is first constructed with a value type as a parameter, the runtime creates a specialized
generic type with the supplied parameter or parameters substituted in the appropriate locations in the MSIL.
Specialized generic types are created one time for each unique value type that is used as a parameter.

For example, suppose your program code declared a stack that is constructed of integers:

C#
Stack<int> stack;

At this point, the runtime generates a specialized version of the Stack<(Of <(T>)>) class that has the integer
substituted appropriately for its parameter. Now, whenever your program code uses a stack of integers, the
runtime reuses the generated specialized Stack<(Of <(T>)>) class. In the following example, two instances
of a stack of integers are created, and they share a single instance of the Stack<int> code:

C#
Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();

However, suppose that another Stack<(Of <(T>)>) class with a different value type such as a long or a user-
defined structure as its parameter is created at another point in your code. As a result, the runtime generates
another version of the generic type and substitutes a long in the appropriate locations in MSIL. Conversions
are no longer necessary because each specialized generic class natively contains the value type.

Generics work somewhat differently for reference types. The first time a generic type is constructed with any
reference type, the runtime creates a specialized generic type with object references substituted for the
parameters in the MSIL. Then, every time that a constructed type is instantiated with a reference type as its
parameter, regardless of what type it is, the runtime reuses the previously created specialized version of the
generic type. This is possible because all references are the same size.

For example, suppose you had two reference types, a Customer class and an Order class, and also suppose
that you created a stack of Customer types:
C#
class Customer { }
class Order { }

C#
Stack<Customer> customers;

At this point, the runtime generates a specialized version of the Stack<(Of <(T>)>) class that stores object
references that will be filled in later instead of storing data. Suppose the next line of code creates a stack of
another reference type, which is named Order:

C#
Stack<Order> orders = new Stack<Order>();

Unlike with value types, another specialized version of the Stack<(Of <(T>)>) class is not created for the
Order type. Instead, an instance of the specialized version of the Stack<(Of <(T>)>) class is created and the
orders variable is set to reference it. Suppose that you then encountered a line of code to create a stack of a
Customer type:

C#
customers = new Stack<Customer>();

As with the previous use of the Stack<(Of <(T>)>) class created by using the Order type, another instance of
the specialized Stack<(Of <(T>)>) class is created. The pointers that are contained therein are set to
reference an area of memory the size of a Customer type. Because the number of reference types can vary
wildly from program to program, the C# implementation of generics greatly reduces the amount of code by
reducing to one the number of specialized classes created by the compiler for generic classes of reference
types.

Moreover, when a generic C# class is instantiated by using a value type or reference type parameter,
reflection can query it at runtime and both its actual type and its type parameter can be ascertained.

Generics Sample
This sample shows how to create a custom generic list class that has a single type parameter, and how to
implement IEnumerable<T> to enable foreach iteration over the contents of the list. The sample also shows
how client code creates an instance of the class by specifying a type argument, and how constraints on the
type parameter enable additional operations to be performed on the type arguments.
For an example of a generic collection class that implements an iterator block, see How to: Create an Iterator
Block for a Generic List (C# Programming Guide).

To get samples and instructions for installing them


Do one or more of the following:

On the Help menu, click Samples.


The Readme displays information about samples.
Visit the Visual Studio 2008 Samples Web site. The most recent versions of samples are available there.
Locate samples on the computer on which Visual Studio is installed. By default, samples and a Readme file are
installed in drive:\Program Files\Microsoft Visual Studio 9.0\Samples\lcid. For Express editions of Visual
Studio, all samples are located online.
For more information, see Locating Sample Files.

Security Note:
This sample code is intended to illustrate a concept, and it shows only the code that is relevant to that
concept. It may not meet the security requirements for a specific environment, and it should not be used
exactly as shown. We recommend that you add security and error-handling code to make your projects more
secure and robust. Microsoft provides this sample code "AS IS" with no warranties.
To build and run the Generics sample within Visual Studio
On the Debug menu, click Start Without Debugging.

To build and run the Generics sample from a command prompt


Type the following at the command prompt:

csc generics.cs
generics

Generic Type Parameters


In a generic type or method definition, a type parameters is a placeholder for a specific type that a client
specifies when they instantiate a variable of the generic type. A generic class, such as GenericList<T> listed in
Introduction to Generics (C# Programming Guide), cannot be used as-is because it is not really a type; it is
more like a blueprint for a type. To use GenericList<T>, client code must declare and instantiate a
constructed type by specifying a type argument inside the angle brackets. The type argument for this
particular class can be any type recognized by the compiler. Any number of constructed type instances can be
created, each one using a different type argument, as follows:

C#
GenericList<float> list1 = new GenericList<float>();
GenericList<ExampleClass> list2 = new GenericList<ExampleClass>();
GenericList<ExampleStruct> list3 = new GenericList<ExampleStruct>();

In each of these instances of GenericList<T>, every occurrence of T in the class will be substituted at run time
with the type argument. By means of this substitution, we have created three separate type-safe and efficient
objects using a single class definition. For more information on how this substitution is performed by the CLR,
see Generics in the Run Time (C# Programming Guide).

Type Parameter Naming Guidelines


Do name generic type parameters with descriptive names, unless a single letter name is completely self
explanatory and a descriptive name would not add value.

C#
public interface ISessionChannel<TSession> { /*...*/ }
public delegate TOutput Converter<TInput, TOutput>(TInput from);
public class List<T> { /*...*/ }

Consider using T as the type parameter name for types with one single letter type parameter.

C#
public int IComparer<T>() { return 0; }
public delegate bool Predicate<T>(T item);
public struct Nullable<T> where T : struct { /*...*/ }

Do prefix descriptive type parameter names with “T”.

C#
public interface ISessionChannel<TSession>
{
TSession Session { get; }
}

Consider indicating constraints placed on a type parameter in the name of parameter. For example, a
parameter constrained to ISession may be called TSession.

Introduction to Generics
Generic classes and methods combine reusability, type safety and efficiency in a way that their non-generic
counterparts cannot. Generics are most frequently used with collections and the methods that operate on
them. Version 2.0 of the .NET Framework class library provides a new namespace,
System.Collections.Generic, which contains several new generic-based collection classes. It is recommended
that all applications that target the .NET Framework 2.0 and later use the new generic collection classes
instead of the older non-generic counterparts such as ArrayList. For more information, see Generics in the
.NET Framework Class Library (C# Programming Guide).

Of course, you can also create custom generic types and methods to provide your own generalized solutions
and design patterns that are type-safe and efficient. The following code example shows a simple generic
linked-list class for demonstration purposes. (In most cases, you should use the List<(Of <(T>)>) class
provided by the .NET Framework class library instead of creating your own.) The type parameter T is used in
several locations where a concrete type would ordinarily be used to indicate the type of the item stored in the
list. It is used in the following ways:

As the type of a method parameter in the AddHead method.

As the return type of the public method GetNext and the Data property in the nested Node class.

As the type of the private member data in the nested class.

Note that T is available to the nested Node class. When GenericList<T> is instantiated with a concrete type,
for example as a GenericList<int>, each occurrence of T will be replaced with int.

C#
// type parameter T in angle brackets
public class GenericList<T>
{
// The nested class is also generic on T.
private class Node
{
// T used in non-generic constructor.
public Node(T t)
{
next = null;
data = t;
}

private Node next;


public Node Next
{
get { return next; }
set { next = value; }
}

// T as private member data type.


private T data;

// T as return type of property.


public T Data
{
get { return data; }
set { data = value; }
}
}

private Node head;


// constructor
public GenericList()
{
head = null;
}

// T as method parameter type:


public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}

public IEnumerator<T> GetEnumerator()


{
Node current = head;

while (current != null)


{
yield return current.Data;
current = current.Next;
}
}
}

The following code example shows how client code uses the generic GenericList<T> class to create a list of
integers. Simply by changing the type argument, the following code could easily be modified to create lists of
strings or any other custom type:

C#
class TestGenericList
{
static void Main()
{
// int is the type argument
GenericList<int> list = new GenericList<int>();

for (int x = 0; x < 10; x++)


{
list.AddHead(x);
}

foreach (int i in list)


{
System.Console.Write(i + " ");
}
System.Console.WriteLine("\nDone");
}
}

System.Collections.Generic Namespace

The System.Collections.Generic namespace contains interfaces and classes that define generic collections,
which allow users to create strongly typed collections that provide better type safety and performance than
non-generic strongly typed collections.
Classes

Class Description
Comparer<(Of <(T>)>) Provides a base class for implementations of
the IComparer<(Of <(T>)>) generic
interface.
Dictionary<(Of <(TKey, TValue>)>) Represents a collection of keys and values.
Dictionary<(Of <(TKey, TValue>)>)..::.KeyCollection Represents the collection of keys in a
Dictionary<(Of <(TKey, TValue>)>). This class cannot be inherited.
Dictionary<(Of <(TKey, TValue>)>)..::.ValueCollection Represents the collection of values in a
Dictionary<(Of <(TKey, TValue>)>). This class cannot be inherited.
EqualityComparer<(Of <(T>)>) Provides a base class for implementations of
the IEqualityComparer<(Of <(T>)>) generic
interface.
HashSet<(Of <(T>)>) Represents a set of values.
KeyedByTypeCollection<(Of <(TItem>)>) Provides a collection whose items are types
that serve as keys.
KeyNotFoundException The exception that is thrown when the key
specified for accessing an element in a
collection does not match any key in the
collection.
LinkedList<(Of <(T>)>) Represents a doubly linked list.
LinkedListNode<(Of <(T>)>) Represents a node in a LinkedList<(Of
<(T>)>). This class cannot be inherited.
List<(Of <(T>)>) Represents a strongly typed list of objects that can be accessed by index. Provides
methods to search, sort, and manipulate lists.
Queue<(Of <(T>)>) Represents a first-in, first-out collection of objects.
SortedDictionary<(Of <(TKey, TValue>)>) Represents a collection of key/value pairs that
are sorted on the key.
SortedDictionary<(Of <(TKey, TValue>)>)..::.KeyCollection Represents the collection of keys in a
SortedDictionary<(Of <(TKey, TValue>)>).
This class cannot be inherited.
SortedDictionary<(Of <(TKey, TValue>)>)..::.ValueCollection Represents the collection of values in a
SortedDictionary<(Of <(TKey, TValue>)>).
This class cannot be inherited
SortedList<(Of <(TKey, TValue>)>) Represents a collection of key/value pairs that
are sorted by key based on the associated
IComparer<(Of <(T>)>) implementation.
Stack<(Of <(T>)>) Represents a variable size last-in-first-out (LIFO) collection of instances of the same
arbitrary type.
SynchronizedCollection<(Of <(T>)>) Provides a thread-safe collection that contains
objects of a type specified by the generic
parameter as elements.
SynchronizedKeyedCollection<(Of <(K, T>)>) Provides a thread-safe collection that contains
objects of a type specified by a generic
parameter and that are grouped by keys.
SynchronizedReadOnlyCollection<(Of <(T>)>) Provides a thread-safe, read-only collection
that contains objects of a type specified by
the generic parameter as elements.

Structures
Structure Description
Dictionary<(Of <(TKey, TValue>)>)..::.Enumerator Enumerates the elements of a
Dictionary<(Of <(TKey, TValue>)>).
Dictionary<(Of <(TKey, TValue>)>)..::.KeyCollection..::.Enumerator Enumerates the elements of a
Dictionary<(Of <(TKey,
TValue>)>)..::.KeyCollection.
Dictionary<(Of <(TKey, TValue>)>)..::.ValueCollection..::.Enumerator Enumerates the elements of a
Dictionary<(Of <(TKey,
TValue>)>)..::.ValueCollection.
HashSet<(Of <(T>)>)..::.Enumerator Enumerates the elements of a
HashSet<(Of <(T>)>) object.
KeyValuePair<(Of <(TKey, TValue>)>) Defines a key/value pair that can be
set or retrieved.
LinkedList<(Of <(T>)>)..::.Enumerator Enumerates the elements of a
LinkedList<(Of <(T>)>).
List<(Of <(T>)>)..::.Enumerator Enumerates the elements of a List<(Of
<(T>)>).
Queue<(Of <(T>)>)..::.Enumerator Enumerates the elements of a
Queue<(Of <(T>)>).
SortedDictionary<(Of <(TKey, TValue>)>)..::.Enumerator Enumerates the elements of a
SortedDictionary<(Of <(TKey,
TValue>)>).
SortedDictionary<(Of <(TKey, TValue>)>)..::.KeyCollection..::.Enumerator Enumerates the elements of a
SortedDictionary<(Of <(TKey,
TValue>)>)..::.KeyCollection.
SortedDictionary<(Of <(TKey, TValue>)>)..::.ValueCollection..::.Enumerator Enumerates the elements of a
SortedDictionary<(Of <(TKey,
TValue>)>)..::.ValueCollection.
Stack<(Of <(T>)>)..::.Enumerator Enumerates the elements of a
Stack<(Of <(T>)>).
Interfaces
Interface Description
ICollection<(Of <(T>)>) Defines methods to manipulate generic collections.
IComparer<(Of <(T>)>) Defines a method that a type implements to compare two objects.
IDictionary<(Of <(TKey, TValue>)>) Represents a generic collection of key/value pairs.
IEnumerable<(Of <(T>)>) Exposes the enumerator, which supports a simple iteration over a
collection of a specified type.
IEnumerator<(Of <(T>)>) Supports a simple iteration over a generic collection.
IEqualityComparer<(Of <(T>)>) Defines methods to support the comparison of objects for equality.
IList<(Of <(T>)>) Represents a collection of objects that can be individually accessed by index.

Hashtable class
What is the Hashtable?
The Hashtable class represents a collection of key/value pairs that are organized based on the hash code of
the key. Each element is a key/value pair stored in a DictionaryEntry object. A key cannot be a null
reference , but a value can be.

Things To Keep In Mind When Creating The Hashtable


The objects used as keys by a Hashtable are required to override the Object.GetHashCode method (or the
IHashCodeProvider interface) and the Object.Equals method (or the IComparer interface). The implementation
of both methods and interfaces must handle case sensitivity the same way; otherwise, the Hashtable might
behave incorrectly. For example, when creating a Hashtable, you must use the
CaseInsensitiveHashCodeProvider class (or any case-insensitive IHashCodeProvider implementation) with the
CaseInsensitiveComparer class (or any case-insensitive IComparer implementation). Furthermore, these
methods must produce the same results when called with the same parameters while the key exists in the
Hashtable.

An alternative is to use a Hashtable constructor with an IEqualityComparer parameter. If key equality were
simply reference equality, the inherited implementation of Object.GetHashCode and Object.Equals would
suffice. Key objects must be immutable as long as they are used as keys in the Hashtable.
How The Hashtable Works
When an element is added to the Hashtable, the element is placed into a bucket based on the hash code of
the key. Subsequent lookups of the key use the hash code of the key to search in only one particular bucket,
thus substantially reducing the number of key comparisons required to find an element. The load factor of a
Hashtable determines the maximum ratio of elements to buckets. Smaller load factors cause faster average
lookup times at the cost of increased memory consumption. The default load factor of 1.0 generally provides
the best balance between speed and size.

A different load factor can also be specified when the Hashtable is created. As elements are added to a
Hashtable, the actual load factor of the Hashtable increases. When the actual load factor reaches the specified
load factor, the number of buckets in the Hashtable is automatically increased to the smallest prime number
that is larger than twice the current number of Hashtable buckets.

Each key object in the Hashtable must provide its own hash function, which can be accessed by calling
GetHash. However, any object implementing IHashCodeProvider can be passed to a Hashtable constructor,
and that hash function is used for all objects in the table. The capacity of a Hashtable is the number of
elements the Hashtable can hold. As elements are added to a Hashtable, the capacity is automatically
increased as required through reallocation. The foreach statement of the C# language requires the type of
each element in the collection.

Since each element of the Hashtable is a key/value pair, the element type is not the type of the key or the
type of the value. Instead, the element type is DictionaryEntry. The foreach statement is a wrapper around
the enumerator, which only allows reading from, not writing to, the collection. Because serializing and
deserializing an enumerator for a Hashtable can cause the elements to become reordered, it is not possible to
continue enumeration without calling the Reset method. Because keys can be inherited and their behavior
changed, their absolute uniqueness cannot be guaranteed by comparisons using the Equals method.

Code Examples
Adding Elements To The Table
// Add some elements to the hash table. There are no duplicate keys, but some of the values are duplicates.
exampleTable.Add( "txt", "notepad.exe" );
exampleTable.Add( "bmp", "paint.exe" );
exampleTable.Add( "dib", "paint.exe" );
exampleTable.Add( "rtf", "wordpad.exe" );
Using The Default Item Property To Change Its Corresponding Key
// The default Item property can be used to change the value associated with a key.
exampleTable[ "rtf" ] = "winword.exe";

// If a key does not exist, setting the default Item property


// for that key adds a new key/value pair.
exampleTable[ "doc" ] = "winword.exe";

//ContainsKey can be used to test keys before inserting them.


if( !exampleTable.ContainsKey( "ht" ) )
{
exampleTable.Add( "ht", "hypertrm.exe" );
}
Using The Remove Method To Delete A Value Or Key From The Table
// Use the Remove method to remove a key/value pair.
exampleTable.Remove( "doc" );
Hashtable Class

Represents a collection of key/value pairs that are organized based on the hash code of the key.

Namespace: System.Collections
Assembly: mscorlib (in mscorlib.dll)
Syntax
Visual Basic (Declaration)
<SerializableAttribute> _
<ComVisibleAttribute(True)> _
Public Class Hashtable _
Implements IDictionary, ICollection, IEnumerable, ISerializable, _
IDeserializationCallback, ICloneable
Visual Basic (Usage)
Dim instance As Hashtable
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public class Hashtable : IDictionary, ICollection,
IEnumerable, ISerializable, IDeserializationCallback, ICloneable

Remarks
Each element is a key/value pair stored in a DictionaryEntry object. A key cannot be nullNothingnullptra null
reference (Nothing in Visual Basic), but a value can be.

The objects used as keys by a Hashtable are required to override the Object..::.GetHashCode method (or the
IHashCodeProvider interface) and the Object..::.Equals method (or the IComparer interface). The
implementation of both methods and interfaces must handle case sensitivity the same way; otherwise, the
Hashtable might behave incorrectly. For example, when creating a Hashtable, you must use the
CaseInsensitiveHashCodeProvider class (or any case-insensitive IHashCodeProvider implementation) with the
CaseInsensitiveComparer class (or any case-insensitive IComparer implementation).

Furthermore, these methods must produce the same results when called with the same parameters while the
key exists in the Hashtable. An alternative is to use a Hashtable constructor with an IEqualityComparer
parameter. If key equality were simply reference equality, the inherited implementation of
Object..::.GetHashCode and Object..::.Equals would suffice.

Key objects must be immutable as long as they are used as keys in the Hashtable.

When an element is added to the Hashtable, the element is placed into a bucket based on the hash code of
the key. Subsequent lookups of the key use the hash code of the key to search in only one particular bucket,
thus substantially reducing the number of key comparisons required to find an element.

The load factor of a Hashtable determines the maximum ratio of elements to buckets. Smaller load factors
cause faster average lookup times at the cost of increased memory consumption. The default load factor of
1.0 generally provides the best balance between speed and size. A different load factor can also be specified
when the Hashtable is created.

As elements are added to a Hashtable, the actual load factor of the Hashtable increases. When the actual load
factor reaches the specified load factor, the number of buckets in the Hashtable is automatically increased to
the smallest prime number that is larger than twice the current number of Hashtable buckets.

Each key object in the Hashtable must provide its own hash function, which can be accessed by calling
GetHash. However, any object implementing IHashCodeProvider can be passed to a Hashtable constructor,
and that hash function is used for all objects in the table.

The capacity of a Hashtable is the number of elements the Hashtable can hold. As elements are added to a
Hashtable, the capacity is automatically increased as required through reallocation.

vb#c#
The foreach statement of the C# language (for each in Visual Basic) requires the type of each element in the
collection. Since each element of the Hashtable is a key/value pair, the element type is not the type of the key
or the type of the value. Instead, the element type is DictionaryEntry. For example:

C#
foreach (DictionaryEntry de in myHashtable) {...}
Visual Basic Copy Code
For Each de as DictionaryEntry In myHashtable
...
Next de
vb#c#
The foreach statement is a wrapper around the enumerator, which only allows reading from, not writing to,
the collection.

Because serializing and deserializing an enumerator for a Hashtable can cause the elements to become
reordered, it is not possible to continue enumeration without calling the Reset method.

Note:
Because keys can be inherited and their behavior changed, their absolute uniqueness cannot be guaranteed
by comparisons using the Equals method.

Examples
The following example shows how to create, initialize and perform various functions to a Hashtable and how to
print out its keys and values.

Visual Basic Copy Code


Imports System
Imports System.Collections

Module Example

Sub Main()

' Create a new hash table.


'
Dim openWith As New Hashtable()

' Add some elements to the hash table. There are no


' duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe")
openWith.Add("bmp", "paint.exe")
openWith.Add("dib", "paint.exe")
openWith.Add("rtf", "wordpad.exe")

' The Add method throws an exception if the new key is


' already in the hash table.
Try
openWith.Add("txt", "winword.exe")
Catch
Console.WriteLine("An element with Key = ""txt"" already exists.")
End Try

' The Item property is the default property, so you


' can omit its name when accessing elements.
Console.WriteLine("For key = ""rtf"", value = {0}.", _
openWith("rtf"))
' The default Item property can be used to change the value
' associated with a key.
openWith("rtf") = "winword.exe"
Console.WriteLine("For key = ""rtf"", value = {0}.", _
openWith("rtf"))

' If a key does not exist, setting the default Item property
' for that key adds a new key/value pair.
openWith("doc") = "winword.exe"

' ContainsKey can be used to test keys before inserting


' them.
If Not openWith.ContainsKey("ht") Then
openWith.Add("ht", "hypertrm.exe")
Console.WriteLine("Value added for key = ""ht"": {0}", _
openWith("ht"))
End If

' When you use foreach to enumerate hash table elements,


' the elements are retrieved as KeyValuePair objects.
Console.WriteLine()
For Each de As DictionaryEntry In openWith
Console.WriteLine("Key = {0}, Value = {1}", _
de.Key, de.Value)
Next de

' To get the values alone, use the Values property.


Dim valueColl As ICollection = openWith.Values

' The elements of the ValueCollection are strongly typed


' with the type that was specified for hash table values.
Console.WriteLine()
For Each s As String In valueColl
Console.WriteLine("Value = {0}", s)
Next s

' To get the keys alone, use the Keys property.


Dim keyColl As ICollection = openWith.Keys

' The elements of the KeyCollection are strongly typed


' with the type that was specified for hash table keys.
Console.WriteLine()
For Each s As String In keyColl
Console.WriteLine("Key = {0}", s)
Next s

' Use the Remove method to remove a key/value pair.


Console.WriteLine(vbLf + "Remove(""doc"")")
openWith.Remove("doc")

If Not openWith.ContainsKey("doc") Then


Console.WriteLine("Key ""doc"" is not found.")
End If

End Sub

End Module
' This code example produces the following output:
'
'An element with Key = "txt" already exists.
'For key = "rtf", value = wordpad.exe.
'For key = "rtf", value = winword.exe.
'Value added for key = "ht": hypertrm.exe
'
'Key = dib, Value = paint.exe
'Key = txt, Value = notepad.exe
'Key = ht, Value = hypertrm.exe
'Key = bmp, Value = paint.exe
'Key = rtf, Value = winword.exe
'Key = doc, Value = winword.exe
'
'Value = paint.exe
'Value = notepad.exe
'Value = hypertrm.exe
'Value = paint.exe
'Value = winword.exe
'Value = winword.exe
'
'Key = dib
'Key = txt
'Key = ht
'Key = bmp
'Key = rtf
'Key = doc
'
'Remove("doc")
'Key "doc" is not found.

C#
using System;
using System.Collections;

class Example
{
public static void Main()
{
// Create a new hash table.
//
Hashtable openWith = new Hashtable();

// Add some elements to the hash table. There are no


// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");

// The Add method throws an exception if the new key is


// already in the hash table.
try
{
openWith.Add("txt", "winword.exe");
}
catch
{
Console.WriteLine("An element with Key = \"txt\" already exists.");
}

// The Item property is the default property, so you


// can omit its name when accessing elements.
Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]);

// The default Item property can be used to change the value


// associated with a key.
openWith["rtf"] = "winword.exe";
Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]);

// If a key does not exist, setting the default Item property


// for that key adds a new key/value pair.
openWith["doc"] = "winword.exe";

// ContainsKey can be used to test keys before inserting


// them.
if (!openWith.ContainsKey("ht"))
{
openWith.Add("ht", "hypertrm.exe");
Console.WriteLine("Value added for key = \"ht\": {0}", openWith["ht"]);
}

// When you use foreach to enumerate hash table elements,


// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( DictionaryEntry de in openWith )
{
Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}

// To get the values alone, use the Values property.


ICollection valueColl = openWith.Values;

// The elements of the ValueCollection are strongly typed


// with the type that was specified for hash table values.
Console.WriteLine();
foreach( string s in valueColl )
{
Console.WriteLine("Value = {0}", s);
}

// To get the keys alone, use the Keys property.


ICollection keyColl = openWith.Keys;

// The elements of the KeyCollection are strongly typed


// with the type that was specified for hash table keys.
Console.WriteLine();
foreach( string s in keyColl )
{
Console.WriteLine("Key = {0}", s);
}

// Use the Remove method to remove a key/value pair.


Console.WriteLine("\nRemove(\"doc\")");
openWith.Remove("doc");

if (!openWith.ContainsKey("doc"))
{
Console.WriteLine("Key \"doc\" is not found.");
}
}
}

/* This code example produces the following output:

An element with Key = "txt" already exists.


For key = "rtf", value = wordpad.exe.
For key = "rtf", value = winword.exe.
Value added for key = "ht": hypertrm.exe

Key = dib, Value = paint.exe


Key = txt, Value = notepad.exe
Key = ht, Value = hypertrm.exe
Key = bmp, Value = paint.exe
Key = rtf, Value = winword.exe
Key = doc, Value = winword.exe

Value = paint.exe
Value = notepad.exe
Value = hypertrm.exe
Value = paint.exe
Value = winword.exe
Value = winword.exe

Key = dib
Key = txt
Key = ht
Key = bmp
Key = rtf
Key = doc

Remove("doc")
Key "doc" is not found.
*/

Inheritance Hierarchy
System..::.Object
System.Collections..::.Hashtable
System.Configuration..::.SettingsAttributeDictionary
System.Configuration..::.SettingsContext
System.Data..::.PropertyCollection
System.Printing.IndexedProperties..::.PrintPropertyDictionary

Thread Safety
Hashtable is thread safe for use by multiple reader threads and a single writing thread. It is thread safe for
multi-thread use when only one of the threads perform write (update) operations, which allows for lock-free
reads provided that the writers are serialized to the Hashtable. To support multiple writers all operations on
the Hashtable must be done through the wrapper returned by the Synchronized method, provided that there
are no threads reading the Hashtable object.
Enumerating through a collection is intrinsically not a thread safe procedure. Even when a collection is
synchronized, other threads can still modify the collection, which causes the enumerator to throw an
exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire
enumeration or catch the exceptions resulting from changes made by other threads.

ICloneable
The System.ICloneable interface defines a method of cloning—copying—to create a new instance of a class
with the identical value as an existing instance.

There are two ways to clone an instance:

Shallow copy - may be linked to data shared by both the original and the copy
Deep copy - contains the complete encapsulated data of the original object
A shallow copy is by far the easiest way to clone your class. This can be achieved with the MemberwiseClone
method inherited by all classes from Object. However, you may find that this is not exactly what you want.

Syntax
Declaration syntax
[ComVisibleAttribute(true)]
public interface ICloneable[edit]Method syntax
The Clone method creates a new object—a copy of the current instance.

Object Clone ()Returns a new object that is a copy of the current instance.

Example scenario
To illustrate the differences between deep and shallow copies, the following scenario has been created. In
addition to a string variable, a Job class contains a reference to a Duties class.

Job class
class Job
{
string m_JobName;
Duties m_Duties;

public Job(string jobName)


{
m_JobName = jobName;
}

public string getJobName()


{
return m_JobName;
}

public void setDuties(string DutyA, string DutyB)


{
m_Duties = new Duties(DutyA, DutyB);
}

public Duties getDuties()


{
return m_Duties;
}
}Duties class
class Duties
{
string m_DutyA;
string m_DutyB;

public Duties(string dutyA, string dutyB)


{
m_DutyA = dutyA;
m_DutyB = dutyB;
}

public string getDutyA()


{
return m_DutyA;
}

public string getDutyB()


{
return m_DutyB;
}
}Person class
class Person : ICloneable
{
string m_Name;
int m_Age;
Job m_CurrentJob;

public Person(string name, int age)


{
m_Name = name;
m_Age = age;
}

public void getJob(Job jobName)


{
m_CurrentJob = jobName;
}

public Job getCurrentJob()


{
return m_CurrentJob;
}

public override string ToString()


{
return this.m_Name;
}

public object Clone()


{
return this.MemberwiseClone(); // call clone method
}
}ICloneableExample class
class ICloneableExample
{
static void Main()
{
Job swimPool = new Job(" Swimming Pool Attendant ");
swimPool.setDuties("rescue swimmers in difficulty ",
"water quality control ");
Person nicola = new Person("Nicola", 23);
nicola.getJob(swimPool);

Person nicolaClone = (Person)nicola.Clone(); // clone

Console.WriteLine("(Nicola)");
printInfo(nicola);
Console.WriteLine("(NicolaClone)");
printInfo(nicolaClone);

Console.WriteLine("\r\n *NicolaClones' Job Duties change* \r\n");


nicolaClone.getCurrentJob().setDuties("Clean Pool",
"Welcome Customers");

Console.WriteLine("(Nicola)");
printInfo(nicola);
Console.WriteLine("(NicolaClone)");
printInfo(nicolaClone);
}

static void printInfo(Person person)


{
Console.WriteLine("Name: {0}", person);
Console.WriteLine(" Job: {0}",
person.getCurrentJob().getJobName());
Console.WriteLine(" Duty A: {0}",
person.getCurrentJob().getDuties().getDutyA());
Console.WriteLine(" Duty B: {0}",
person.getCurrentJob().getDuties().getDutyB());
}
}MemberwiseClone
The Person.Clone method simply calls the Object.MemberwiseClone method to make a shallow copy of the
instance.

ICloneableExample (program output)


(Nicola)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control
(NicolaClone)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control

*NicolaClones' Job Duties change*

(Nicola)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: Clean Pool
Duty B: Welcome Customers
(NicolaClone)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: Clean Pool
Duty B: Welcome Customers

Notice that the duties of both the original and the clone have changed.

Shallow copy example


What has been created above is called a shallow copy. Meaning, only the top level class is actually copied to
the heap. If that top level class contains any references to instances, only the references will be copied. So,
original and clone are exactly the same object, hence why changing duties for one copy changes both copies.

To demonstrate this further, a shallow change can be done—for example: changing the person’s name.

Person Class - Additional method

public void changeName(string name)


{
m_Name = name;
}Updated Main method

static void Main()


{
Job swimPool = new Job(" Swimming Pool Attendant ");
swimPool.setDuties("rescue swimmers in difficulty ", "water quality control ");

Person nicola = new Person("Nicola", 23);


nicola.getJob(swimPool);

Person nicolaClone = (Person)nicola.Clone();

Console.WriteLine("(Nicola)");
printInfo(nicola);
Console.WriteLine("(NicolaClone)");
printInfo(nicolaClone);

Console.WriteLine("\r\n *NicolaClone changes name* \r\n");


nicolaClone.changeName("Becky");

Console.WriteLine("(Nicola)");
printInfo(nicola);
Console.WriteLine("(NicolaClone)");
printInfo(nicolaClone);
}

ICloneableExample (program output)


(Nicola)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control
(NicolaClone)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control

*NicolaClone changes name*


(Nicola)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control
(NicolaClone)
Name: Becky
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control

Notice how the name has changed. Although a string is a reference type it has been copied due to it being a
system type.

[edit]Deep copy example


In a Deep copy, the clone method requires additional code to create new instances of any classes referenced
by the original.

This example uses the first version of Main.

Updated Clone method

public object Clone()


{
Person Copy = new Person(this.m_Name, this.m_Age);
Job CopyJob = new Job(this.m_CurrentJob.getJobName());
CopyJob.setDuties (this.m_CurrentJob.getDuties().getDutyA(),
this.m_CurrentJob.getDuties().getDutyB());
Copy.getJob(CopyJob);

return Copy;

ICloneableExample (program output)


(Nicola)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control
(NicolaClone)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control
*NicolaClones' Job Duties change*

(Nicola)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: rescue swimmers in difficulty
Duty B: water quality control
(NicolaClone)
Name: Nicola
Job: Swimming Pool Attendant
Duty A: Clean Pool
Duty B: Welcome Customers
Design to be cloned
In the previous example, all cloning was done by just one class, the Person class. This means that the Person
class must understand how to clone not only itself, but also a Job and the Jobs' Duties. Although this does
mean that all cloning is done in one place it does not support the 'OO' principal of encapsulation. That is to
say that if a class could be used in a different project then it should be able to work without the user class
understanding the inner workings. To support this each class can have its own Clone method.

The following shows how a class can be designed or changed to allow the use of class cloning which in turn
promotes encapsulation.

Clone-unfriendly example
class Job : ICloneable
{
string m_JobName;
Duties m_Duties;

public Job(string jobName)


{
m_JobName = jobName;
}

public string getJobName()


{
return m_JobName;
}

/*********************************************************
* This should be phased out ASAP! *
* If Duties change this will have to be changed *
* This goes against encapsulation rules where public *
* methods should always remain the same. *
*********************************************************/
public void setDuties(string DutyA, string DutyB)
{
m_Duties = new Duties(DutyA, DutyB);
}

public Duties getDuties()


{
return m_Duties;
}

public object Clone()


{
Job copy = new Job(this.m_JobName);

/*****************************************************************
* The Job class must understand how to set duties. *
* If Duties change then the Job class will also have to change! *
*****************************************************************/
copy.setDuties(this.m_Duties.getDutyA(),this.m_Duties.getDutyB());

return copy;
}

}
Clone-friendly example -
class Job : ICloneable
{
string m_JobName;
Duties m_Duties;

public Job(string jobName)


{
m_JobName = jobName;
}

public string getJobName()


{
return m_JobName;
}

/*********************************************************
* Overload the method, this allows the existing *
* method to remain for older code which uses it. *
* *
* This design works even if the Duties class is changed! *
*********************************************************/
public void setDuties(Duties duties)
{
m_Duties = duties;
}

public Duties getDuties()


{
return m_Duties;
}

public object Clone()


{
Job copy = new Job(this.m_JobName);

/******************************************************
* Duties knows more about itself than any other class *
* So let it clone itself! *
******************************************************/
copy.setDuties((Duties) this.m_Duties.Clone());

return copy;
}

}
The final main classes
The clone friendly classes follow:

class Person : ICloneable


{
string m_Name;
int m_Age;
Job m_CurrentJob;

public Person(string name, int age)


{
m_Name = name;
m_Age = age;
}

public void getJob(Job jobName)


{
m_CurrentJob = jobName;
}

public Job getCurrentJob()


{
return m_CurrentJob;
}

public void changeName(string name)


{
m_Name = name;
}

public override string ToString()


{
return this.m_Name;
}

#region ICloneable Members

public object Clone()


{
Person Copy = new Person(this.m_Name, this.m_Age);
Copy.getJob((Job) this.getCurrentJob().Clone());

return Copy;
}
#endregion
}class Job : ICloneable
{
string m_JobName;
Duties m_Duties;

public Job(string jobName)


{
m_JobName = jobName;
}

public string getJobName()


{
return m_JobName;
}

public void setDuties(Duties duties)


{
m_Duties = duties;
}

public Duties getDuties()


{
return m_Duties;
}

#region ICloneable Members

public object Clone()


{
Job copy = new Job(this.m_JobName);
copy.setDuties((Duties) this.m_Duties.Clone());

return copy;
}

#endregion
}class Duties: ICloneable
{
string m_DutyA;
string m_DutyB;

public Duties(string dutyA, string dutyB)


{
m_DutyA = dutyA;
m_DutyB = dutyB;
}

public string getDutyA()


{
return m_DutyA;
}

public string getDutyB()


{
return m_DutyB;
}

#region ICloneable Members

public object Clone()


{
Duties copy = new Duties(this.m_DutyA, this.m_DutyB);
return copy;
}

#endregion
}

Example
Note that only a slight change had to be made in the way that duties are set due to phasing out the clone-
unfriendly method.

static void Main()


{
Job swimPool = new Job(" Swimming Pool Attendant ");
swimPool.setDuties (
new Duties("rescue swimmers in difficulty ",
"water quality control "));
Person nicola = new Person("Nicola", 23);
nicola.getJob(swimPool);

Person nicolaClone = (Person)nicola.Clone();

Console.WriteLine("(Nicola)");
printInfo(nicola);
Console.WriteLine("(NicolaClone)");
printInfo(nicolaClone);

Console.WriteLine("\r\n *NicolaClones' Job Duties change* \r\n");


nicolaClone.getCurrentJob().setDuties (
new Duties("Clean Pool", "Welcome Customers"));

Console.WriteLine("(Nicola)");
printInfo(nicola);
Console.WriteLine("(NicolaClone)");
printInfo(nicolaClone);
}

static void printInfo(Person person)


{
Console.WriteLine("Name: {0}", person);
Console.WriteLine(" Job: {0}",
person.getCurrentJob().getJobName());
Console.WriteLine(" Duty A: {0}",
person.getCurrentJob().getDuties().getDutyA());
Console.WriteLine(" Duty B: {0}",
person.getCurrentJob().getDuties().getDutyB());
}

ICloneable Interface
Supports cloning, which creates a new instance of a class with the same value as an existing instance.

Namespace: System
Assembly: mscorlib (in mscorlib.dll)
Syntax
Visual Basic (Declaration)
<ComVisibleAttribute(True)> _
Public Interface ICloneable
Visual Basic (Usage)
Dim instance As ICloneable
C#
[ComVisibleAttribute(true)]
public interface ICloneable

Remarks
The ICloneable interface contains one member, Clone, which is intended to support cloning beyond that
supplied by MemberwiseClone.

Object..::.MemberwiseClone Method
Creates a shallow copy of the current Object.

Namespace: System
Assembly: mscorlib (in mscorlib.dll)
Syntax
Visual Basic (Declaration)
Protected Function MemberwiseClone As Object
Visual Basic (Usage)
Dim returnValue As Object

returnValue = Me.MemberwiseClone()
C#
protected Object MemberwiseClone()

Return Value
Type: System..::.Object
A shallow copy of the current Object.

Remarks
The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the
nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field
is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the
original object and its clone refer to the same object.

For example, consider an object called X that references objects A and B. Object B, in turn, references object
C. A shallow copy of X creates new object X2 that also references objects A and B. In contrast, a deep copy of
X creates a new object X2 that references the new objects A2 and B2, which are copies of A and B. B2, in
turn, references the new object C2, which is a copy C. Use a class that implements the ICloneable interface to
perform a deep or shallow copy of an object.

Examples
The following code example shows how to copy an instance of a class using MemberwiseClone.

Visual Basic
Imports System

Class MyBaseClass
Public Shared CompanyName As String = "My Company"
Public age As Integer
Public name As String
End Class 'MyBaseClass

Class MyDerivedClass
Inherits MyBaseClass

Shared Sub Main()

' Creates an instance of MyDerivedClass and assign values to its fields.


Dim m1 As New MyDerivedClass()
m1.age = 42
m1.name = "Sam"

' Performs a shallow copy of m1 and assign it to m2.


Dim m2 As MyDerivedClass = CType(m1.MemberwiseClone(), MyDerivedClass)

End Sub 'Main

End Class 'MyDerivedClass

C#
using System;

class MyBaseClass {
public static string CompanyName = "My Company";
public int age;
public string name;
}

class MyDerivedClass: MyBaseClass {

static void Main() {

// Creates an instance of MyDerivedClass and assign values to its fields.


MyDerivedClass m1 = new MyDerivedClass();
m1.age = 42;
m1.name = "Sam";

// Performs a shallow copy of m1 and assign it to m2.


MyDerivedClass m2 = (MyDerivedClass) m1.MemberwiseClone();
}
}

IComparable
The System.IComparable interface defines a generalized comparison method to be implemented by a value
type or class. It is used to create a type-specific method for comparing and ordering instances.

Generic version (preferred)


Syntax
Declaration syntax
public interface IComparable<T>The IComparable interface defines the CompareTo method:

Method syntax
int CompareTo (T comparee)where comparee is an object to be compared with this object.

Return value Meaning


Less than zero (< 0) Comparer < Comparee
Zero (0) Comparer = Comparee
Greater than zero (> 0) Comparer > Comparee

Usage
Simple equality (==) example
class Vector
{
private double m_X, double m_Y, double m_Z;

public Vector(double x, double y, double z)


{
m_X = x;
m_Y = y;
m_Z = z;
}

public double getX() { return m_X; }

public double getY() { return m_Y; }

public double getZ() { return m_Z; }


}Vector myVA = new Vector(1.5, 1.5, 1.5);
Vector myVB = new Vector(1.5, 1.5, 1.5);
if (myVA == myVB)
{
Console.WriteLine("myVA = myVB");
}
else
{
Console.WriteLine("myVA != myVB");
}Output:
myVA != myVBThe reason for this result is that the == compares the value stored in the variables myVA and
myVB. Because these represent instances of classes, they are reference types; so, the values are memory
addresses where the actual objects are stored on the heap. Therefore, they can never be identical unless they
actually point to the same object as follows:

Vector myVA = new Vector(1.5, 1.5, 1.5);


Vector myVB = myVA;

if (myVA == myVB)
{
Console.WriteLine("myVA = myVB");
}
else
{
Console.WriteLine("myVA != myVB");
}Output:
myVA = myVB[edit]CompareTo()
When implementing IComparable you a must create a CompareTo(Comparee) method which returns an int
indicating three main states:

Return value Meaning


Less than zero (< 0) Comparer < Comparee
Zero (0) Comparer = Comparee
Greater than zero (> 0) Comparer > Comparee

This means you must give some thought to what you actually want to compare of the class.

With the Vector class the most likely attribute to compare is the magnitude. With this in mind the Vector class
now becomes:

class Vector : IComparable<Vector>


{
private double m_Xm double m_Y, double m_Z;

public Vector(double x, double y, double z)


{
m_X = x;
m_Y = y;
m_Z = z;
}

public double getX() { return m_X; }

public double getY() { return m_Y; }

public double getZ() { return m_Z; }

#region IComparable<Vector> Members


public int CompareTo(Vector other)
{
Double magnitudeThis = 0;
Double magnitudeThat = 0;
int returnValue = 0;

magnitudeThis += Math.Pow(m_X, 2);


magnitudeThis += Math.Pow(m_Y, 2);
magnitudeThis += Math.Pow(m_Z, 2);

magnitudeThat += Math.Pow(other.getX(), 2);


magnitudeThat += Math.Pow(other.getY(), 2);
magnitudeThat += Math.Pow(other.getZ(), 2);

magnitudeThis = Math.Sqrt(magnitudeThis);
magnitudeThat = Math.Sqrt(magnitudeThat);

//In practice catch the exception!


returnValue = Convert.ToInt32((magnitudeThis - magnitudeThat));

return returnValue;
}

#endregion
}Vector myVA = new Vector(1.5, 1.5, 1.5);
Vector myVB = new Vector(1.5, 1.5, 1.5);

if (myVA.CompareTo(myVB) == 0)
{
Console.WriteLine("myVA = myVB");
}
else
{
Console.WriteLine("myVA != myVB");
}Output:
myVA = myVB[edit]Non-generic version (backward compatible)
[edit]Syntax
[edit]Declaration syntax
[ComVisibleAttribute(true)]
public interface IComparable[edit]Method syntax
The IComparable interface defines the CompareTo method:

int CompareTo (Object comparee)where comparee is an object to be compared with this object.

Non-Generic type checking


If you do not use the generic IComparable, then you must type check the comparee object and either cast it
within the CompareTo method or throw an exception if it is not comparable. This means that possible errors
will now only be caught at runtime instead of compile time.

Note: The example now has extra code as it has to check for this exception and, also, have to cast the object
each time.
class Vector : IComparable
{
private double m_X, double m_Y, double m_Z;

public Vector(double x, double y, double z)


{
m_X = x;
m_Y = y;
m_Z = z;
}

public double getX() { return m_X; }

public double getY() { return m_Y; }

public double getZ() { return m_Z; }

#region IComparable Members

public int CompareTo(object obj)


{
if (obj is Vector)
{
Vector that = (Vector) obj;

Double magnitudeThis = 0;
Double magnitudeThat = 0;
int returnValue = 0;

magnitudeThis += Math.Pow(m_X, 2);


magnitudeThis += Math.Pow(m_Y, 2);
magnitudeThis += Math.Pow(m_Z, 2);

magnitudeThat += Math.Pow(that.getX(), 2);


magnitudeThat += Math.Pow(that.getY(), 2);
magnitudeThat += Math.Pow(that.getZ(), 2);

magnitudeThis = Math.Sqrt(magnitudeThis);
magnitudeThat = Math.Sqrt(magnitudeThat);

//In practice catch the exception!


returnValue = Convert.ToInt32((magnitudeThis - magnitudeThat));

return returnValue;
}

throw new ArgumentException("Object cannot be compared");


}
#endregion
}

IComparable Interface

Defines a generalized type-specific comparison method that a value type or class implements to order or sort
its instances.

Namespace: System
Assembly: mscorlib (in mscorlib.dll)
Syntax
Visual Basic (Declaration)
<ComVisibleAttribute(True)> _
Public Interface IComparable
Visual Basic (Usage)
Dim instance As IComparable
C#
[ComVisibleAttribute(true)]
public interface IComparable

Remarks
This interface is implemented by types whose values can be ordered or sorted. It requires that implementing
types define a single method, CompareTo, that indicates whether the position of the current instance in the
sort order is before, after, or the same as a second object of the same type. The instance's IComparable
implementation is called automatically by methods such as Array..::.Sort and ArrayList..::.Sort.

All numeric types (such as Int32 and Double) implement IComparable, as do String, Char, and DateTime.
Custom types should also provide their own implementation of IComparable to enable object instances to be
ordered or sorted.

Examples
The following code sample illustrates the implementation of IComparable and the requisite CompareTo
method.

Visual Basic
Imports System.Collections

Public Class Temperature


Implements IComparable
' The temperature value
Protected temperatureF As Double

Public Overloads Function CompareTo(ByVal obj As Object) As Integer _


Implements IComparable.CompareTo

If TypeOf obj Is Temperature Then


Dim otherTemperature As Temperature = DirectCast(obj, Temperature)
Return Me.temperatureF.CompareTo(otherTemperature.temperatureF)
Else
Throw New ArgumentException("Object is not a Temperature")
End If
End Function

Public Property Fahrenheit() As Double


Get
Return temperatureF
End Get
Set(ByVal Value As Double)
Me.temperatureF = Value
End Set
End Property

Public Property Celsius() As Double


Get
Return (temperatureF - 32) * (5/9)
End Get
Set(ByVal Value As Double)
Me.temperatureF = (Value * 9/5) + 32
End Set
End Property
End Class
Public Module CompareTemperatures
Public Sub Main()
Dim temperatures As New ArrayList
' Initialize random number generator.
Dim rnd As New Random()

' Generate 10 temperatures between 0 and 100 randomly.


For ctr As Integer = 1 To 10
Dim degrees As Integer = rnd.Next(0, 100)
Dim temp As New Temperature
temp.Fahrenheit = degrees
temperatures.Add(temp)
Next

' Sort ArrayList.


temperatures.Sort()

For Each temp As Temperature In temperatures


Console.WriteLine(temp.Fahrenheit)
Next
End Sub
End Module
' The example displays the following output to the console (individual
' values may vary because they are randomly generated):
' 2
' 7
' 16
' 17
' 31
' 37
' 58
' 66
' 72
' 95

C#
using System;
using System.Collections;

public class Temperature : IComparable


{
// The temperature value
protected double temperatureF;

public int CompareTo(object obj) {


if(obj is Temperature)
{
Temperature otherTemperature = (Temperature) obj;
return this.temperatureF.CompareTo(otherTemperature.temperatureF);
}
else
{
throw new ArgumentException("Object is not a Temperature");
}
}

public double Fahrenheit


{
get
{
return this.temperatureF;
}
set {
this.temperatureF = value;
}
}

public double Celsius


{
get
{
return (this.temperatureF - 32) * (5/9);
}
set
{
this.temperatureF = (value * 9/5) + 32;
}
}
}

public class CompareTemperatures


{
public static void Main()
{
ArrayList temperatures = new ArrayList();
// Initialize random number generator.
Random rnd = new Random();

// Generate 10 temperatures between 0 and 100 randomly.


for (int ctr = 1; ctr <= 10; ctr++)
{
int degrees = rnd.Next(0, 100);
Temperature temp = new Temperature();
temp.Fahrenheit = degrees;
temperatures.Add(temp);
}

// Sort ArrayList.
temperatures.Sort();

foreach (Temperature temp in temperatures)


Console.WriteLine(temp.Fahrenheit);
}
}
// The example displays the following output to the console (individual
// values may vary because they are randomly generated):
// 2
// 7
// 16
// 17
// 31
// 37
// 58
// 66
// 72
// 95

Das könnte Ihnen auch gefallen