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

List of .NET 2.0 and C# 2.0 new features

, 24 Feb 2006
Rate this:
Please Sign up or sign in to vote.
A list of .NET 2.0 and C# 2.0 new features.

Title Practical .NET2 and C#2
Author Patrick Smacchia
Publisher ParadoxalPress
Published January 2006
ISBN 0-9766132-2-0
Price USD 59.95 (ParadoxalPress price: USD 33.99)
Pages 896
Website www.PracticalDOT.NET (Browse and download the 647 listings and sample chapters)

The list of .NET 2.0 and C# 2.0 new features is extracted from the appendix of the book Practical .NET2 and C#2. All mentioned features are thoroughly covered in the book.

Contents

Assembly

The use of the AssemblyKeyFile attribute to sign an assembly is to be avoided. It is now preferred that you use the /keycontainer and /keyfile options of csc.exe, or the new project properties of Visual Studio 2005.

The new System.Runtime.CompilerServices.InternalsVisibleToAttribute attribute allows you to specify assemblies which have access to non-public types within the assembly to which you apply the attribute (kind of 'assemblies friendship').

The ildasm.exe 2.0 tool offers, by default, the possibility of obtaining statistics in regards to the byte size of each section of an assembly and the display of its metadata. With ildasm.exe 1.x, you needed to use the /adv command line option.

Application localization

The resgen.exe tool can now generate C# or VB.NET code which encapsulates access to resources in a strongly typed manner.

Application build process

The .NET platform is now delivered with a new tool called msbuild.exe. This tool is used to build .NET applications and is used by Visual Studio 2005, but you can use it to launch your own build scripts.

Application configuration

The .NET 2.0 platform features a new, strong typed management of your configuration parameters. Visual Studio 2005 also contains a configuration parameter editor which generates the code needed to take advantage of this feature.

Application deployment

The new deployment technology named ClickOnce allows a fine management of the security, updates, as well as on-demand installation of applications. Visual Studio 2005 offers some practical facilities to take advantage of this technology.

CLR

A major bug with version 1.x of the CLR which made it possible to modify signed assemblies has been addressed in version 2.

The System.GC class offers two new methods named AddMemoryPressure() and RemoveMemoryPressure() which allow you to give the GC an indication in regards to the amount of unmanaged memory held. Another method CollectionCount(int generation) allows you to know the number of collections applied to the specified generation.

New features have been added to the ngen.exe tool to support assemblies using reflection, and to automate the update of the compiled version of an assembly when one of its dependencies has changed.

The ICLRRuntimeHost interface used from unmanaged code to host the CLR replaces the ICorRuntimeHost interface. It allows access to a new API permitting the CLR to delegate a certain number of core responsibilities such as the loading of assemblies, thread management, or the management of memory allocations. This API is currently only used by the runtime host for SQL Server 2005.

Three new mechanisms named Constrained Execution Region (CER), Critical Finalizer, and Critical Region (CR) allow advanced developers to increase the reliability of applications such SQL Server 2005 which are likely to deal with a shortage of system resources.

A memory gate mechanism can be used to evaluate, before an operation, if sufficient memory is available.

You can now quickly terminate a process by calling the FailFast() static method which is part of the System.Environment class. This method bypasses certain precautions such as the execution of finalizers or the pending finally blocks.

Delegate

A delegate can now reference a generic method or a method that is part of a generic type. We then see appearing the notion of generic delegates.

With the new overloads of the Delegate.CreateDelegate(Type, Object, MethodInfo) method, it is now possible to reference a static method and its first argument from a delegate. The calls to the delegates then do not need this first argument and is similar to the use of instance method calls.

In addition, the invocation of methods through the use of delegates is now more efficient.

Threading/Synchronization

You can easily pass information to a new thread that you created by using the new ParametrizedThreadStart delegate. Also, new constructors of the Thread class allow you to set the maximum size of the thread stack in bytes.

The Interlocked class offers new methods and allows to deal with more types such as IntPtr or double.

The WaitHandle class offers a new static method named SignalAndWait(). In addition, all classes deriving from WaitHandle offer a new static method named OpenExisting().

The EventWaitHandle can be used instead of its subclasses AutoResetEvent and ManualResetEvent. In addition, it allows to name an event and thus share it amongst multiple processes.

The new class Semaphore allows you take advantage of Win32 semaphores from your managed code.

The new method SetMaxThreads() of the ThreadPool class allows to modify the maximal number of threads within the CLR thread pool from managed code.

The .NET 2.0 framework offers new classes which allow to capture and propagate the execution context of the current thread to another thread.

Security

The System.Security.Policy.Gac class allows the representation of a new type of evidence based on the presence of an assembly in the GAC.

The following new permission classes have been added: System.Security.Permissions.KeyContainerPermission, System.Net.NetworkInformation.NetworkInformationPermission, System.Security.Permissions.DataProtectionPermission, System.Net.Mail.SmtpPermission, System.Data.SqlClient.SqlNotificationPermission, System.Security.Permissions.StorePermission, System.Configuration.UserSettingsPermission, System.Transactions.DistributedTransactionPermission, and System.Security.Permissions.GacIdentityPermission.

The IsolatedStorageFile class presents the following new methods: GetUserStoreForApplication(), GetMachineStoreForAssembly(), GetMachineStoreForDomain(), and GetMachineStoreForApplication().

The .NET 2.0 framework allows to launch a child process within a different security context than the parent process.

The .NET 2.0 framework offers new types within the System.Security.Principal namespace allowing the representation and manipulation of Windows security identifiers.

The .NET 2.0 framework presents new types within the System.Security.AccessControl namespace to manipulate Windows access control settings.

The .NET 2.0 framework offers new hashing methods within the System.Security.Cryptography namespace.

The .NET 2.0 framework offers several classes giving access to the functionality offered by the Windows Data Protection API (DAPI).

The System.Configuration.Configuration class allows the easy management of the application configuration file. In particular, you can use it to encrypt your configuration data.

The .NET 2.0 framework offers new types within the System.Security.Cryptography.X509Certificates and System.Security.Cryptography.Pkcs namespaces which are specialized for the manipulation of X.509 and CMS/Pkcs7 certificates.

The new namespace named System.Net.Security offers the new classes SslStream and NegociateStream which allow the use of the SSL, NTLM, and Kerberos security protocols to secure data streams.

Reflection/Attribute

You now have the possibility of loading an assembly in reflection-only mode. Also, the AppDomain class offers a new event named ReflectionOnlyAssemblyResolve triggered when the resolution of an assembly fails in the reflection-only context.

The .NET 2.0 framework introduces the notion of conditional attribute. Such an attribute has the particularity of being taken into consideration by the C# 2 compiler only when a certain symbol is defined.

Interoperability

The notion of function pointers and delegates are now interchangeable using the new GetDelegateForFunctionPointer() and GetFunctionPointerForDelegate() methods of the Marshal class.

The HandleCollector class allows you to supply to the garbage collector an estimate on the number of Windows handles currently held.

The new SafeHandle and CriticalHandle classes allow to harness Windows handles more safely than with the IntPtr class.

The tlbimp.exe and tlbexp.exe tools present a new option named /tlbreference which allow the explicit definition of a type library without having to go through the registry. This allows the creation of compilation environments which are less fragile.

Visual Studio 2005 offers features to take advantage of the reg-free COM technology of Windows XP within a .NET application. This technology allows the use of a COM class without needing to register it into the registry.

Structures related to COM technology such as BINDPTR, ELEMDESC, and STATDATA have been moved from the System.Runtime.InteropServices namespace to the new System.Runtime.InteropServices.ComTypes namespace. This namespace contains new interfaces which redefine certain standard COM interfaces such as IAdviseSink or IConnectionPoint.

The new namespace named System.Runtime.InteropServices contains new interfaces such as _Type, _MemberInfo, or _ConstructorInfo which allow unmanaged code to have access to reflection services. Of course, the related managed classes (Type, MemberInfo, ConstructorInfo...) implement these interfaces.

C# 2.0

Undoubtedly, the highlight feature in .NET 2.0 and C# 2.0 is generics.

C# 2.0 allows the declaration of anonymous methods (which can be seen as closures).

C# 2.0 presents a new syntax to define iterators.

The csc.exe compiler offers the following new options /keycontainer, /keyfile, /delaysign, /errorreport and /langversion.

C# 2.0 brings forth the notions of namespace alias qualifier, of global:: qualifier, and of external alias to avoid certain identifier conflicts.

C# 2.0 introduces the new compiler directives #pragma warning disable and #pragma warning restore.

The C# 2.0 compiler is now capable of inferring a delegation type during the creation of a delegate object. This makes source code more readable.

The .NET 2.0 framework introduces the notion of nullable types which can be exploited through a special C# 2.0 syntax.

C# 2.0 now allows you to spread the definition of a type across multiple source files within the same module. This new feature is called partial type.

C# 2.0 allows the assignment of a different visibility to the accessor of a property or indexer.

C# 2.0 allows the definition of static classes.

C# 2.0 now allows the definition of a table field with a fixed number of primitive elements within a structure.

Visual Studio 2005 intellisense feature now uses the XML information contained within /// comments.

Visual Studio 2005 allows you to build UML-like class diagrams in-sync with your code.

Exceptions

The SecurityException class and Visual Studio 2005 have been improved to allow you to more easily test and debug your mobile code.

The Visual Studio 2005 debugger offers a practical wizard to obtain a complete set of information relating to an exception.

Visual Studio 2005 allows you to be notified when a problematic event known by the CLR occurs. These events sometime provoke managed exceptions.

Collections

The whole set of collection types within the .NET framework have been revised in order to account for generic types. Here is a comparison chart between the System.Collections and System.Collections.Generic namespaces.

System.Collections.Generics

System.Collections

Comparer<T>

Comparer

Dictionary<K,T>

HashTable

List<T> LinkedList<T>

ArrayList

Queue<T>

Queue

SortedDictionary<K,T> SortedList<K,T>

SortedList

Stack<T>

Stack

ICollection<T>

ICollection

IComparable<T>

System.IComparable

IComparer<T>

IComparer

IDictionary<K,T>

IDictionary

IEnumerable<T>

IEnumerable

IEnumerator<T>

IEnumerator

IList<T>

IList

The System.Array class has no generic equivalent and is still current. Indeed, since the beginning of .NET, the collection model proposed by this class supports a certain level of genericity. It presents new methods such as void Resize<T>(ref T[] array, int newSize), void ConstrainedCopy(...), and IList<T> AsReadOnly(T[] array).

Debugging

The System.Diagnostics namespace provides new attributes DebuggerDisplayAttribute, DebuggerBrowsable, DebuggerTypeProxyAttribute, and DebuggerVisualizerAttribute which allow you to customize the display of the state of your objects while debugging.

.NET 2.0 allows indicating through attributes the assemblies, modules, or zones of code that you do not wish to debug. This feature is known as Just My Code.

C# 2.0 programmers now have access to the Edit and Continue feature allowing them to modify their code while debugging it.

.NET 2.0 presents the new enumeration named DebuggableAttribute.DebuggingModes which is a set of binary flags on the debugging modes we wish to use.

Base classes

The primitive types (integer, boolean, floating point numbers) now expose a method named TryParse() which allows to parse a value within a string without raising an exception in the case of failure.

The .NET 2.0 framework offers several implementations derived from the System.StringComparer abstract class which allows to compare strings in a culture and case sensitive manner.

The new Sytem.Diagnostics.Stopwatch class is provided especially to accurately measure elapsed time.

The new DriveInfo class allows the representation and manipulation of volumes.

The .NET 2.0 framework introduces the notion of trace source allowing a better management of traces. Also, the following trace listener classes have been added: ConsoleTraceListener, DelimitedListTraceListener, XmlWriterTraceListener, and WebPageTraceListener.

Several new functionalities have been added to the System.Console class in order to improve data display.

IO

The .NET 2.0 framework offers the new class System.Net.HttpListener which allows to take advantage of the HTTP.SYS component of Windows XP SP2 and Windows Server 2003 to develop a HTTP server.

In .NET 2.0, the classes that are part of the System.Web.Mail namespace are now obsolete. To send mail, you must use the classes within the System.Net.Mail namespace. This new namespace now contains classes to support the MIME standard.

New methods now allow you to read and write a file in a single call.

New classes are now available to compress/decompress a data stream.

A new unmanaged version System.IO.UnmanagedMemoryStream of the MemoryStream class allows you to avoid copying of data onto the CLR’s object heap and is thus more efficient.

The new System.Net.FtpWebRequest class implements a FTP client.

The new namespace System.Net.NetworkInformation contains types which allow to query the network interfaces available on a machine in order to know their states, their traffic statistics, and to be notified on state changes.

Web resource caching services are now available in the new System.Net.Cache namespace.

The new System.IO.Ports.SerialPort class allows the use of a serial port in a synchronous or event based manner.

Windows Forms 2.0

Visual Studio 2005 takes advantage of the notion of partial classes in the management of Windows Forms. Hence, it will not mix anymore the generated code with our own code in the same file.

Windows Forms 2.0 offers the BackgroundWorker class which standardizes the development of asynchronous operations within a form.

The appearance (i.e. the visual style) of controls is better managed by Windows Forms 2.0 as it does not need to use the comctl32.dll DLL to obtain a Windows XP style.

Windows Forms 2.0 and Visual Studio 2005 contain the framework and development tools for a quick and easy development of presentation and edition windows for data.

Windows Forms 2.0 presents the new classes BufferedGraphicsContext and BufferedGraphics which allow a fine control on a double buffering mechanism.

The ToolStrip, MenuStrip, StatusStrip, and ContextMenuStrip controls: these controls, respectively, replace the ToolBar, MainMenu, StatusBar, and ContextMenu controls (which are still present for backward compatibility reasons). In addition to nicer visual style, these new controls are particularly easy to manipulate during the design of a window, thanks to a consistent API. New functionality has been added such as the possibility of sharing a render between controls, the support for animated GIFs, opacity, transparency, and the facility of saving the current state (position, size…) in the configuration file. The hierarchy of the classes derived from the class System.Windows.Forms.ToolStripItem constitutes as many elements which can be inserted in this type of control.

The DataGridView and BindingNavigator controls: these controls are part of a new framework to develop data driven forms. This framework is the subject of the Viewing and editing data section a little later in this chapter. Know that it is now preferable to use a DataGridView for the display of any data table or list of objects instead of the Windows Forms 1.0 DataGrid control.

The FlowLayoutPanel and TableLayout controls: these controls allow the dynamic positioning of the child controls that it contains when the user modifies its size. The layout philosophy of the FlowLayoutPanel control is to list the child controls horizontally or vertically in a way where they are moved when the control is resized. This approach is similar to what we see when we resize an HTML document displayed by a browser. The layout philosophy of the TablePanel control is comparable to the anchoring mechanism where the child controls are resized based on the size of the parent control. However, here the child controls are found in the cells of a table.

The SplitterPanel and SplitContainer controls: the combined use of these controls allows the easy implementation of splitting of a window in a way that it can be resized, as we had with version 1.1 using the Splitter control.

The WebBrowser control: this control allows the insertion of a web browser directly in a Windows Forms form.

The MaskedTextBox control: this control displays a TextBox in which the format of the text to insert is constrained. Several types of masks are offered by default, such as dates or US telephone number. Of course, you can also provide your own masks.

The SoundPlayer and SystemSounds controls: the SoundPlayer class allows you to play sounds in .wav format while the SystemSounds class allows you to retrieve the system sounds associated with the current user of the operating system.

ADO.NET 2.0

ADO.NET 2.0 presents new abstract classes such as DbConnection or DbCommand in the new namespace System.Data.Common which implements the IDbConnection or IDbCommand interfaces. The use of these new classes is now preferred to the use of the interfaces.

ADO.NET 2.0 offers an evolved architecture of abstract factory classes which allow decoupling the data access code from the underlying data provider.

ADO.NET 2.0 presents new features to construct connection strings independently of the underlying data provider.

ADO.NET 2.0 offers a framework allowing the programmatic traversal of a RDBMS schema.

The indexing engine used internally by the framework when you use instances of the DataSet and DataTable classes have been revised in order to be more efficient during the loading and manipulation of data.

Instances of the DataSet and DataTable classes are now serializable into a binary form using the new SerializationFormat RemotingFormat{get;set;} property. You can achieve a gain of 3 to 8 times in relation to the use of XML serialization.

The DataTable class is now less dependant on the DataSet class as the XML features of this one have been added.

The new method DataTable DataView.ToTable() allows the construction of a DataTable containing a copy of a view.

ADO.NET 2.0 now offers a bridge between the connected and disconnected modes which allow the DataSet/DataTable and DataReader classes to work together.

Typed DataSets directly take into account the notion of relationships between tables. Now, thanks to partial types, the generated code is separated from your own code. Finally, the new notion of TableAdapter allows you to create some sort of typed SQL requests directly usable from your code.

ADO.NET 2.0 allows to store data updates in a more efficient manner, thanks to batch updates.

ADO.NET 2.0: SQL Server data provider (SqlClient)

You now have the possibility of enumerating SQL Server data sources.

You have more control on connection pooling.

The SqlClient data provider of ADO.NET 2.0 allows the execution of commands in an asynchronous way.

You can harness the bulk copy services of the SQL Server tool bcp.exe using the SqlBulkCopy class.

You can obtain statistics about the activity of a connection.

There is a simplified and freely distributed version of SQL Server 2005 which offers several advantages over the previous MSDE and Jet products.

Transaction

The new namespace named System.Transactions (contained in the Systems.Transactions.dll) offers, at the same time, a unified transactional programming model and a new transactional engine which has the advantage of being extremely efficient on certain types of lightweight transactions.

XML

The performance of all classes involved in XML data handling have been significantly improved (by a factor of 2 to 4 in classic use scenarios according to Microsoft).

The new System.Xml.XmlReaderSettings class allows to specify the type of verifications which must be done when using a subclass of XmlReader to read XML data.

It is now possible to partially validate a DOM tree loaded within an instance of XmlDocument.

It is now possible to modify a DOM tree stored in an XmlDocument instance through the XPathNavigator cursor API.

The XslCompiledTransform class replaces the XslTransform class which is now obsolete. Its main advantage is in compiling XSLT programs into MSIL code before applying a transformation. According to Microsoft, this new implementation improves performance by a factor of 3 to 4. Moreover, Visual Studio 2005 can now debug XSLT programs.

Support for the XML DataSet class has been improved. You can now load XSD schemas with names repeated in different namespaces, and load XML data containing multiple schemas. Also, XML load and save methods have been added to the DataTable class.

The 2005 version of SQL Server brings forth new features in regards to the integration of XML data inside a relational database.

XML serialization can now serialize nullable information and generic instances. Also, a new tool named sgen.exe allows the pre-generation of an assembly containing the code to serialize a type.

.NET Remoting

The new IpcChannel channel is dedicated to the communication between different processes on a same machine. Its implementation is based on the notion of Windows named pipe.

If you use a channel of type TCP, you now have the possibility of using the NTLM and Kerberos protocols to authenticate the Windows user under which the client executes, to encrypt the exchanged data and impersonate your requests.

New attributes of the System.Runtime.Serialization namespace allow the management of problems inherent to the evolution of a serializable class.

It is possible to consume an instance of a closed generic type, with the .NET Remoting technology, whether you are in CAO or WKO mode.

ASP.NET 2.0

Visual Studio .NET 2005 is now supplied with a web server which allows the testing and debugging of your web applications during development.

It is now easy to use the HTTP.SYS component to build a web server which hosts ASP.NET without needing to use IIS.

ASP.NET 2.0 presents a new model for the construction of classes representing web pages. This model is based on partial classes, and is different than the one offered in ASP.NET 1.x.

The CodeBehind directive of ASP.NET v1.x is no longer supported.

In ASP.NET 2.0, the model used for dynamic compilation of your web application has significantly improved, and is now based on several new standard folders. In addition, ASP.NET 2.0 offers two new pre-compilation modes: the in-place pre-compilation, and the deployment pre-compilation.

To counter the effects of large viewstates in ASP.NET 1.x, ASP.NET 2.0 stores information in a base64 string, more efficiently, and introduces the notion of control-state.

ASP.NET 2.0 introduces a new technique which allows to postback a page to another page.

Certain events have been added to the lifecycle of a page.

ASP.NET 2.0 offers an infrastructure to allow the process of the same request across multiple threads of a pool. This allows us to avoid running out of threads within the pool when several long requests are executed at the same time.

New events have been added to the HttpApplication class.

The manipulation of configuration files has been simplified because of the Visual Studio 2005 intellisense, a new web interface, a new UI integrated in IIS, and because of new base classes.

ASP.NET 2.0 offers a framework allowing the standard management of events occurring during the life of a web application.

You can now configure ASP.NET 2.0 so that it can detect whether it is possible to store a session identifier in a client-side cookie, or if it should automatically switch over to the URI mode if cookies are not supported.

ASP.NET 2.0 now allows you to supply your own session or session ID management mechanism.

The cache engine of ASP.NET 2.0 offers interesting new features. You can now use the VaryByControl sub-directive in your pages. You can substitute dynamic fragments within your cached pages. You can associate your cached data dependencies towards tables and rows of a SQL Server data source. Finally, you can create your own types of dependencies.

ASP.NET 2.0 offers new server controls allowing declarative binding to a data source.

ASP.NET 2.0 offers a new hierarchy of server-side controls for the presentation and the edition of data. These controls have the peculiarity of being able to use a data source control to read and write data.

ASP.NET 2.0 offers a simplified template syntax.

ASP.NET 2.0 adds the notion of master pages which allows the easy reuse of a page design across all pages of a website.

ASP.NET 2.0 now offers an extensible architecture to allow insertion of navigational controls within your site.

With ASP.NET 2.0, you can use the Forms authentication mode without being forced to use cookies.

ASP.NET 2.0 allow the management of user authentication data as well of the roles to which they may belong, through the use of a database. Hence, several new server-side controls have been added to greatly simplify the development of ASP.NET applications which support authentication.

ASP.NET 2.0 presents a new framework allowing the storage and access of users' profiles.

ASP.NET 2.0 offers a framework facilitating the management and maintenance of the overall appearance of a site, thanks to the notions of themes and skins.

ASP.NET 2.0 also offers a framework dedicated to the creation of web portals through the use of what is called WebParts.

ASP.NET 2.0 offers a framework allowing the modification of rendered HTML code if the initiating HTTP request comes from a system with a small screen such as a mobile phone. Concretely, the rendering of each server control is done in a way to use less screen space. This modification is done through the use of adapter objects which are requested automatically and implicitly by ASP.NET during the rendering of the page. The "Inside the ASP.NET Mobile Controls" article on MSDN offers a good starting point on this new ASP.NET 2.0 feature.

Web Services

The proxy classes generated by wsdl.exe now offers a new asynchronous model which allows cancellation.

License

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

A list of licenses authors might use can be found here

Share

About the Author

Patrick Smacchia MVP.NET
Web Developer
France France
Patrick Smacchia is a .NET MVP involved in software development for over 15 years. He is the author of Practical .NET2 and C#2, a .NET book conceived from real world experience with 647 compilable code listings. After graduating in mathematics and computer science, he has worked on software in a variety of fields including stock exchange at Société Générale, airline ticket reservation system at Amadeus as well as a satellite base station at Alcatel. He's currently a software consultant and trainer on .NET technologies as well as the author of the freeware NDepend which provides numerous metrics and caveats on any compiled .NET application.

Comments and Discussions

 
QuestionIsn't it a little bit too late? Pinmemberelektrowolf24-Apr-08 10:15 
AnswerRe: Isn't it a little bit too late? PinmemberAnthony_Yio19-May-08 0:51 
GeneralGreate Article Forgot Extension Methods :) PinmemberShay Ben-Sasson28-Oct-07 1:45 
AnswerRe: Greate Article Forgot Extension Methods :) PinmemberShay Ben-Sasson28-Oct-07 1:58 
General.NET 2.0 has a broken serialport class Pinmembertricychloramine11-Dec-06 3:24 
GeneralRe: .NET 2.0 has a broken serialport class Pinmembertricychloramine12-Dec-06 21:30 
GeneralGood Information PinmemberAjith Cyriac6-Sep-06 20:34 
GeneralCode Example PinmemberM_Rizwan28-Feb-06 0:40 
GeneralRe: Code Example Pinmembervgo28-Feb-06 23:58 
GeneralRe: Code Example PinmemberPatrick Smacchia MVP.NET2-Mar-06 5:02 
GeneralRe: Code Example PinmemberHerbert Sauro21-Aug-07 14:19 
GeneralHa! I ordered your book PinprotectorMarc Clifton24-Feb-06 14:30 
GeneralRe: Ha! I ordered your book Pinmembersebfia28-Feb-06 6:42 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 24 Feb 2006
Article Copyright 2006 by Patrick Smacchia MVP.NET
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid