Welcome Guest!
Create Account | Login
Locator+ Code:

FTPOnline Channels Conferences Resources Hot Topics Partner Sites Magazines About FTP RSS 2.0 Feed

Click here to receive your FREE subscription to Visual Studio Magazine

email article
printer friendly

Utilize Constraints in Custom Generic Classes
Learn how constraints work when creating custom generic classes; display the VB splash screen for an extended period of time; and preserve Handles clauses when you cut-and-paste them.
by Kathleen Dollard

August 1, 2007

Technology Toolbox: VB .NET, C#

I'm going to be creating some custom generic classes, but I don't understand the concept of constraints. I've heard that you need constraints to create new objects in the generic class. Can you explain this?

Assume you create a generic class like this one:

public class BizObjectList<T> :List<T>
{ // No additional Funtionality

You don't need constraints in this case because it doesn't matter what T is; you aren't calling any methods or properties of T. T can literally be of any type.

If, however, you want to work with the methods and properties of T, you need to let the compiler know what type to expect, so you can ensure these properties or methods are available. A generic list derived from System.Collections.Generic.List or System.Collections.ObjectModel.Collection that has no constraint can access only methods and properties of Object. This means it can do little more than make a call ToString().

Constraints specify that it is legal only to use the type parameters that meet the constraint, which guarantees to the compiler that the methods and properties of the constraint are accessible:

public class BizList<T> : List<T> 
	where T : BizBase<T>
	public void Save()
		foreach (T item in this)
		{ item.Save(); }

You can call the Save method because it exists on the BizBase<T> class, which is a constraint (Listing 1). The C# syntax defines constraints with the where clause at the end of the class or method declaration. The Visual Basic syntax is a little different:

Public Class BizList(Of T As BizBase( _
	Of T))
	Inherits List(Of T)

	Public Sub Save()
		For Each item As T In Me
	End Sub
End Class

The two most important types of constraints are base class constraints and interface constraints. In both cases, the constraint allows all methods and properties available in scope. You can include combinations of a base class and interfaces.

There is a third type of constraint that isn't all that useful. In order to create a new instance of the type parameter, the compiler needs a guarantee that a constructor is available. Unfortunately, Microsoft made two mistakes in this implementation. Instead of checking for the constructor in scope, it requires that the constructor be public. Expanding the scope of your constructors to use them in generics is not acceptable. The constructor also has to be parameterless. If you're using parameterized constructors to ensure your objects are immediately in a valid state, you're not going to abandon this best practice to use parameterless constructors.

Instead, you must use a little reflection to create your objects.

dim newT as T
newT = TryCast( _
	Activator.CreateInstance(gettype(T)), T)

TryCast is equivalent to the as operator in C# (see the question, "What does TryCast do?" in VSM's June 2007 issue [Q&A, "Whip WPF Snippets Into Shape"]). This code is messier than using new, but you don't have to redesign your constructors. Overloads of the CreateInstance method let you access private constructors and include parameters as an array. Using this method to access private constructors enforces a factory pattern where new objects are created only through this code. Parameters are passed as Object and will be coerced to the correct data type. You can ensure this coercion is based on your tested language if you pass InvariantCulture as the CultureInfo parameter.

I want to display a splash screen for my Visual Basic application. I can get it to display, but it disappears too quickly. How do I make it show longer?

The Visual Basic infrastructure displays a splash screen automatically if you provide one in the Visual Basic project options. The length of time that it displays is one of several infrastructure settings that you can alter by overriding the OnInitialize method (or by handling the Initialize event):

Imports System.Collections.ObjectModel
Protected Overrides Function OnInitialize( _
	ByVal commandLineArgs As _
	ReadOnlyCollection(Of String)) _
	As Boolean
	' Set the display time to 5 seconds 
	Me.MinimumSplashScreenDisplayTime = 5000
	Return MyBase.OnInitialize(commandLineArgs)
End Function

This works for WinForms in Visual Studio 2005, but the application infrastructure settings aren't available for WPF in Visual Studio 2005.

I work in Visual Basic, and I like the declarative approach of the Handles clause for events. But I find it frustrating that the Handles clauses are removed when I cut-and-paste controls, especially when I'm just moving them between tabs. Is there a way to preserve the Handles clauses when I cut-and-paste them?

Visual Studio includes a great tool for viewing the way your forms use containers for nesting; the tool is called the Document Outline. It presents a treeview of all the containers and controls on your form. If you drag controls between containers in the Document Outline, the controls are never removed from the form and thus Visual Studio doesn't remove the Handles clauses. You can find the Document Outline in the main Visual Studio menu in View|Other Windows|Document Outline.

About the Author
Kathleen Dollard has been developing business applications for over 20 years, programming in Visual Basic for ten years, and working with .NET since the early betas. As an independent consultant, she has worked in a variety of domains, including the finance and justice sectors. Kathleen has worked extensively with application code generation and is the author of Code Generation in Microsoft .NET (from Apress). She has published numerous articles on a range of .NET technologies, including WPF, WF, XSLT, debugging, ADO.NET, and code generation. Kathleen is also a member of the INETA speaker's bureau, a long time Microsoft MVP, founding member of the Northern Colorado .NET SIG, and is an active member of the Denver Visual Studio User Group. Contact her at [email protected].

Back to top

Java Pro | Visual Studio Magazine | Windows Server System Magazine
.NET Magazine | Enterprise Architect | XML & Web Services Magazine
VSLive! | Thunder Lizard Events | Discussions | Newsletters | FTPOnline Home