Jump to content

.NET Development Foundation/AllInOne

From Wikibooks, open books for an open world


Microsoft .NET Framework 2.0
Application Development Foundation

Welcome to the "All in one" view page of the Wikibooks's Microsoft certification exam 70-536 study guide. Considering it's size, this page was not configured for editing (please use main page).


Preface

Welcome to the 'Microsoft .NET Framework 2.0 Application Development Foundation' module.

This book provides extensive "textbook like" coverage of the exam objectives associated with exam 70-536 of the Microsoft certification program. Those objectives cover the basic .NET class libraries and the interaction of a program with the .NET execution environment.

Please give us your feedback on the module so we can improve it (see discussion page).

The preface contains information relevant to the context of the document, authors, wikibooks, etc. You can skip to the Introduction if you are primarily interested in the module content.

Audience and other Wikibooks resources

The audience for this study guide are software developers professionally interested in the .NET framework. Microsoft states in the Exam (70-536) preparation guide that "Candidates should have at least two to three years of experience developing Web-based, Microsoft Windows-based, or distributed applications by using the .NET Framework 1.0, the .NET Framework 1.1, and the .NET Framework 2.0. Candidates should have a working knowledge of Visual Studio 2005.".

For this study guide, we will just assume that readers know at least one of the .NET languages (VB.NET, C#, etc.), have access to Visual Studio and have some experience working with it.

Please note that the .NET platform is quite extensive and that a basic understanding of computer science is also assumed. For example, we will briefly discuss how object-orientation principles are implemented in the framework (from a developer point of view) but not the principles themselves, where do they come from, what specific problems they address, etc.

Wikibooks has other books both on VB, C# and .NET that are more introductory in nature:

Finally, by "professionally interested" we refer to the fact that this book, along with the other certification study guides, provides an extensive coverage of the framework and demands a significant study time. So anybody that wants to get that kind of coverage and has some time to spare can join in!

Contributions

This module is far from over! Please do not hesitate to improve it as you see fit.

Just a couple of pointers though if you are a new contributor to wikibooks:

  • Wikibooks are about textbooks not "standard" wikis. The project team is looking for continuous narratives that can be read from top to bottom. For somebody used to the MSDN type of documentation this can be a significant adjustment.
  • Links only pages do not fit the above picture and are actively discouraged. If you create a page, be sure to have content to put on it :-)
  • The administrators use templates to ask questions or notify of incomplete tasks. Those templates produce rather flashy notices that can be surprising at first. Don't worry about the look and ask for clarifications. The admins are very helpful and nice and will help you with whatever you may need.
  • Code samples are very welcome and should be put in "hidden" sections to preserve the flow of the text. see example section. A sample should be kept as short as possible but the space limitations of printed material obviously do not apply here. We thus encourage you to have complete, yet clear and simple, programs so they can be directly tested and used.

Exam information and certifications

Current information on the exam can be found at MSDN Exam Information

This module is the study guide for the first exam (70-536) for obtaining many Microsoft certifications:

Authors

William "Scott" Baker (User:Scott98390)

If you contribute to this book, if you wish, please add your name here. The contributors for a specific article can be traced by its history.

Please note that it is not wikibook's policy to have link only pages or pages with very few text. The preferred way is to have continuous textbooks that can be read from start to finish. The first contributions to this module where in the form of separate pages for each third or forth level exam objectives. This gave way to numerous pages that were merged into more consistent global pages. For links only page, this process had the adverse side effect of losing references to contributions made to those pages. For pages with text the change history were moved to the merged page.


Introduction

Module objectives

This study guide does not aim at replacing the other resources that exist to get prepared to pass the 70-536 exam:

  • we provide links to the MSDN library, we do not try to replace it. People who pass the exam often note that the training kit does not cover every aspect of the exam and that consulting the MSDN documentation is a big plus.
  • we provide links to Wikipedia and other Wikimedia projects where applicable. This is not a series of theoretical or encyclopedia articles but a guide on how the concepts are implemented in the .NET framework and how to use them.
  • we do not provide testing software
  • we do not pretend that this module replaces the recommended training kit or any other recommended material from Microsoft.

What we do provide though, even at this document's grossly incomplete stage, is:

  • an exhaustive list of the objectives of the exam as stated by Microsoft
  • links from all exam objectives to the corresponding MSDN library article.
  • "textbook like" explanations for a growing number of topics with links to related external sources.
  • and most of all, a place to put your important notes and code examples for your revision before the exam and as a reference for your professional work afterward. No training kit or library provides that in a shared and controlled environment.

The most difficult aspect of a book like this one is to keep a balance between having enough content to cover and explain every objective of the exam and not too much content because reading and studying time should be kept to a manageable level. Furthermore, there is no reason to cover content here that is not directly related to exam objectives.

Finally, as part of the Wikimedia family (Wikipedia and all) the Wikibooks project has very high ethics on copyrights and general quality. Do not hesitate to correct if you find anything "wrong" in any way.

Module structure

This module is structured around the objectives set by Microsoft for the 70-536 Exam. Chapters 3 to 9 represents each of the 7 major objective categories of the exam.

The idea behind sticking to the exam "official" objectives is that we assume that somehow the certification provider (Microsoft) has some understanding of the product (.NET) and can state what is important to know about it.

For each chapter:

  • a first section covers the major concepts (topics) treated in that chapter. This "topics" section allows us to somewhat separate the "what" from the "how-to". Please note that the exam is heavily oriented toward the utilization of the libraries and tools and that an understanding of the concepts is highly insufficient as a preparation for the exam.
  • a second section then details each of the second, third and fourth level exam objectives for that objective category (how-to's, detailed usage and references to MSDN library).

Eventually, we would like to have:

  • a "revision questions" section for each chapter where we could discuss the kind of questions that could be asked at the exam.
  • an "advanced" section where we could put the more advanced material and keep the text flow of the basic sections at a level that corresponds to the knowledge required for the exam.

As of December 7, 2007:

  • 24 subjects are detailed on separate pages (the subject title is the link). Most of those will eventually be integrated into the main page for a better flow of the text.
  • all of the subjects are directly linked to the Microsoft Software Developers Network (MSDN) library, about 480 directly from the main page (the "MSDN" following the title is the link) and the others from their respective subpage.
  • we just started to link the "topics" sections to Wikipedia articles to give you a feel of how the concepts are defined and treated outside of Microsoft's world.

Some sections are relatively advanced and others are awaiting your contributions. The more advanced sections are not all at the beginning of the module.

The .NET Framework

In the certification paths where exam 70-536 "Microsoft .NET Framework 2.0 Application Development Foundation" is present, it represents the first step of the certification process. It is thus natural to start this first study guide with a short discussion of the framework as a whole.

The definition on MSDN .NET main page is: "The .NET Framework is Microsoft's managed code programming model for building applications on Windows clients, servers, and mobile or embedded devices. Developers use .NET to build applications of many types: Web applications, server applications, smart client applications, console applications, database applications, and more".

Wikipedia's definition is: "The Microsoft .NET Framework is a software component included with the Microsoft Windows operating system. It provides a large body of pre-coded solutions to common software development requirements, and manages the execution of programs written specifically for the framework. The .NET Framework is intended to be used by most new applications created for the Windows platform"

The problem with Microsoft's definition is that it refers to a "managed code programming model" which is still Microsoft terminology. The best definition for it: "Managed code is code that has its execution managed by the .NET Framework Common Language Runtime" (see Brad Adams blog on MSDN).

Wikipedia's definition points to the two more important aspects from a developer point of view:

  • The presence of a huge set of class libraries that allows for all of the common programming tasks. Beside the sheer size of the those class libraries, they are also evolving at a rapid pace.
  • The fact that the execution environment is specific to the framework. The term "virtual machine" is often used to qualify such an environment.

Those two main characteristics parallel those of the Java environment, which is the main competitor to the .NET framework. This module tries to help you learn the .NET framework. It will not address the .NET vs Java comparisons and discussions.

Framework structure

Visual overview of the Common Language Infrastructure (CLI)

The image on the right is taken from the Wikipedia article on the .NET framework (see above).

It describes the process followed by a program written in a .NET compatible language from source code to execution. The important difference with that and more conventional programming languages (ex. C++) is the fact that the program is compiled twice. The first compilation is done from the original language to a "common intermediate language" (CIL). This is what actually goes "in" an assembly.

The second compilation is done from the CIL to machine code. This compilation is usually performed automatically by the "just-in-time" (JIT) compiler. It is also possible to use the Native Image Generator (ngen) utility to create the machine code in advance of runtime.

This architecture has many direct implications for the subjects of this book. Among them:

  • The "source code" of the second compilation (the CIL code) is always available to the virtual machine at runtime. This means that this code can easily be analyzed at runtime, contrary to conventional compiled environment. This characteristic is the base for the reflection functionality of the platform. Not only can we analyze the "intermediate source code" but we can actually create (emit) some of it at runtime and then do the "just-in-time" compilation and execution.
  • The execution is done in the context of the CLR (this is the "managed" code concept). Put another way, we can say that the runtime always "knows" what it sends for execution, contrary to a conventional environment where the code is executed directly by the operating system. This implies that you can tell the runtime to execute, or not, this or that type of code. This is the basis for code access security.
  • Most of the features of the .NET languages (C#, VB, etc.) are directly related to features of the intermediate language. Put another way, most of the time, the first compilation is pretty straightforward. Some of the constructs though do not have direct equivalents in the CIL (ex. properties in C# are mapped to class methods in the CIL).

We could continue like that for a long time. The point we want to make here is that a developer has much to gain from a detailed understanding of the platform, even if it is not directly mentioned as an objective of the exam.

If you want to read on the framework in Microsoft documentation you can see MSDN.

The last thing we will note here is that the common language runtime (CLR) can execute in different contexts:

  • ASP.NET for web applications, where it is directly linked to the Internet Information Server (IIS).
  • Internet Explorer for client side web controls
  • In a standalone host for console, service and windows applications.

By default, examples in this book will use standalone executables. This is just because they are more easy to deploy for very simple programs. This does not imply that Windows applications are preferable to web applications.

Where this book fits

The .NET stack

The image on the right, also taken from Wikipedia, gives a simplified but clear view of the functional components of the framework.

This book (and the related exam) deals with the "Base Class Library" component and the basic relations of a program with the "Common Language Runtime" component.

The book does not cover ASP.NET, ADO.NET, WF or any other more specialized components.

We can say that we extensively cover the basics but that we shallowly cover the framework itself.

The relations with the common language runtime include such things as:

  • Deployment
  • Security
  • Configuration
  • Reflection
  • Services
  • Relationship with WMI
  • Interoperability
  • etc.

The base class library includes

  • types
  • collections
  • generics
  • text manipulation
  • basic drawing
  • basic globalization
  • serialization
  • basic input/output
  • multi-threading
  • etc.

All in all they are kind of "dry" topics. This idea of starting with an extensive coverage of the basics is certainly not the most interesting learning pattern for a beginner. This is why we advise real beginners to start with more adequate material.

One last note about the framework "stack" is that new versions tend to add new components instead of "redoing" existing ones. This means that most of the "2.0" basics are still valid in "3.5". Some "basic" functionalities are nevertheless augmented or changed in new versions. We will try to keep track of those as side notes where possible.

Programming paradigms

Keeping things very (too much?) simple we can say that a programming paradigm is a "style" of programming, a specific way to model problems and "translate" their solution in code.

From a developer point of view the .NET framework (and its class libraries) is a general-purpose object-oriented platform that is constantly extended to support other programming paradigms (generic programming with Generics, Aspect programming with attributes, Reactive programming with WF, Functional programming with Lambda expressions in C# 3.0, etc.). That "extension process" mirrors that of Java. The .NET and Java platforms are the only two that currently support such extensive multi-paradigms extension process.

Discussing the extent and "theoretical soundness" of each of those paradigm implementations is obviously out of scope for this book.

Our point here is that navigating through all those programming styles in the same platform can get kind of confusing. Maintaining code is also getting more and more difficult because two original programmers could have solved the same problem using widely different "styles" or constructs.

We will thus try to connect, where possible, the different .NET concepts with their respective "style" to give the reader some context.

Assemblies

According to MSDN assemblies are: "the building blocks of .NET Framework applications; they form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions".

The .NET Framework is now Microsoft's preferred way of developing applications on the Windows platform. In that respect it succeeds the Component Object Model (COM). This is important to mention because despite some deployment and management problems (remember DLL Hell?) COM played an important role in the development of component-based computing (reusing whole executable components, not only program code). Major efforts have been invested to transfer the component-based concepts of COM to the .NET framework and a significant part of this book deals with those (security, installation, versioning, etc.).

The assembly is the successor of the COM component.


Clipboard

To do:
a very short list of main assemblies characteristics will go here


System types and collections

Exam objective: Developing applications that use system types and collections.


Topics

Programs, objects and methods

.NET is essentially a set of tools to build and execute computer programs. A computer program is a set of instructions given to a computer that executes those instructions automatically to manipulate some data. .NET follows the object-oriented paradigm which means that the instructions and data are grouped around ‘’objects’’ that represent things or concepts. Objects that share the same instructions and manipulate the same kind of data are grouped into the same type.

An object-oriented program is the definition of a series of types. For each type the kind of data and the instructions are specified. The instructions are grouped inside methods. One of the available instructions is the creation of an object of a defined type. Another kind of instruction is the request to execute a method associated with an object. This is called invoking a method. When a method is invoked its instructions are executed until the method terminates (returns). When the method returns the calling (invoking) method executes its next instruction (statement).

When you start the execution of a program the system creates a first object and invokes a method of that object (this is called the main method). Inside that method other objects are typically created and methods of those objects are invoked. Those methods will invoke other methods and create other objects and so on. Gradually the called methods will return and the '’main’’ method will eventually finish, marking the end of the program execution.

System types

This section will be obvious for experienced object oriented developers but some of the specific objectives of the exam are directly related to the type system.

Types are a way to classify the concepts or objects of a language. The way this classification is organized is called a 'type system'. The types themselves can also be categorized in different ways by the type system.

The first way to categorize types in .NET is to make a difference between types that are part of the framework class libraries (System types) and types that will be constructed by the developer (custom types).

Writing object oriented programs can be seen as the process of defining one or more custom types. Those types are then packaged in some kind of execution unit (Assemblies in the case of .NET). The assemblies are compiled and then executed starting at some entry point that will be a specified method of one of the custom type.

Those custom types use:

  • System types to execute "pre-programmed" instruction sequences
  • other custom types

System types are also packaged in assemblies. The custom assemblies must reference the system assemblies in order to use the System types.

There are other ways to categorize types in .NET. One of them is by the way the objects created based on those types are mapped to the computer memory. This will give us Value types and Reference types.

Another way is by Reflection category (Class, Value types, Interfaces, Generics, etc.).

Yet another way is to distinguish the types that are directly supported by the runtime (built-in types) from those defined either in the class libraries or custom.

Those categories can also be intersected with one another, that will give us such things as "Built-in value types" or "System interfaces". Stay alert of the categorizations used when you encounter such combinations.

Namespaces are a way to organize types so that they can be more easily found. See this for a discussion on namespaces.

In the context of namespaces the System types are the types included in the System namespace or one of its sub-namespace and Custom types (non system types) should use other namespaces.

For a peek at how Microsoft describes the .NET type system see MSDN. And then for an overview of the class libraries (System types) see MSDN.

Most of the exam is in fact based on how to use the common parts of the type libraries (System types). This is why the list of exam objectives (and this book TOC) is so long.

Hello world

For the newcomers to .NET, you may want to take a little break from the concepts here and make sure that you see how the concepts discussed so far are used in a very simple example. The next concepts are not that trivial. We will put such an example here.

Value types

Value types represent one part of the Value / Reference classification of the type system.

An instance of a value type directly contains its data (value). For example an Int32 local variable has its memory allocated directly on the stack.

The value types are themselves split in 3 categories:

  • The built-in value types
  • User-defined value types
  • Enumerations

Remember that built-in types are the types directly supported by the runtime.

They are the building blocks of any program because they are what the machine instructions ultimately act upon. The rest are essentially compositions of those types.

All of the built-in types are value types except for Object and String.

The built-in value types consist of

  • the integer types (Byte, SByte, Int16, Int32, Int64, UInt16, UInt32 and UInt64)
  • the floating point types (Single and Double)
  • the logical type (Boolean)
  • other (Char, Decimal, InPtr and UInPtr)

All built-in value types are defined in the System namespace (ex. System.Int32) and have keywords that represent them in the VB and C# (ex. int in C#, integer in VB.NET) except for InPtr and UInPtr.

Side note

We noted above that type classification can be quite confusing sometimes. As an example note that System.DateTime is presented as a built-in value type in the Training kit (page 5) and this is not identified as an error in MSDN KB. It is not a built-in type according to the official specification (page 19). The confusion comes from the fact that the Training kit does not make a clear difference between System types (in the class libraries) and Build-in types (basic types dealt with directly by the runtime).

The point here is not to be fussy or depreciate the work done by the authors of the training kit. We just want to note that it may be worth to take a few minutes to clearly separate the concepts before heading to the code.

All value types derive from System.ValueType either directly for built-in and user-defined or indirectly through System.Enum for enumerations.

Enumerations are a way to name a set of values of an underlying integer type (signed or unsigned). As restrictions of an integer type they act as their underlying type.

User-defined value types and Enumerations both include System types and Custom types.

An example of a System user-defined value-type would be System.Drawing.Point used in drawing.

You build custom value types using specific language constructs (struct in C#, Structure in VB.NET).

An example of a System enumeration would be the System.Data.CommandType enumeration that specifies if a table is a text command, a call to a stored procedure, etc.

You build custom enumerations using specific language constructs (enum in C#, Enum in VB.NET).

For examples and notes on using value types see this section. See also examples of building and using user-defined value types.

Reference types

Reference types represent the other part of the Value / Reference classification of the type system.

Contrary to value types, an instance of a reference type does not directly contain its data (value), but instead contains some kind of a reference to the memory location of that value. For example a String local variable has memory allocated on the stack for a reference to the contained string, not the string itself. In that case the string itself will be allocated on the heap and garbage collected (more on that later).

Two built-in types are considered reference types: Object and String and they are also directly referenced in the System libraries (ex. System.String) and have their own constructs in the .NET languages (ex. string in C#).

The reference types are themselves split in four categories:

  • pointers
  • arrays
  • classes
  • interfaces

We will not talk about pointers in this book because no exam objective references them.

The next three sections will present arrays, classes and interfaces.

For a comparison of value / reference types try this.

For other notes and an example of using reference types see this.

Arrays

An array is essentially a group of objects, usually of the same type, than can be accessed via an index.

For a general discussion of arrays you can see the Wikipedia article (on the right) or go to the Wikibook on data structures.

Arrays once were one of the most used features of programming languages because you can go from one item in the array to the next in a very efficient way (you can see C pointers and arrays if you want more details on this). Today the availability of much more “computer power” has moved the focus from arrays to collections. The two main problems of arrays are:

  • They are fixed length
  • They support only one internal organization

Collections address most of the shortcomings of arrays (at a cost though). Arrays can still be considered for a fixed group of objects that have to be efficiently manipulated.

We will have some examples in the using arrays section.

Classes

Classes are themselves split in three:

  • user-defined classes
  • boxed value types
  • delegates

Boxed value types will be discussed a little later in the boxing / unboxing section.

Delegates will also be covered later in their section.

User-defined classes are the basic realizations of the object oriented concepts.

Obviously a lot can be said about classes but since no exam objective reference to them we will assume that the reader is already familiar with the concept and have already worked with them (in .NET or elsewhere).

You can have System classes (hundreds and hundreds of them) and custom classes (where you will code the essential of your program logic).

We have examples of using and building classes.

Interfaces

If you want to get really confused on what exactly is object-oriented programming just check the Wikipedia article on Polymorphism :-).

The idea is just to be able to have a single type of reference to the "common part" of different types that have "something in common".

Rectangles and Ellipses are both "Shapes" so how can we get part of a program to manipulate "Shapes" without knowing about the specific of Rectangles or Ellipses. In such a situation we say that Shapes are polymorphic (literally they can take many forms).

In object-oriented programming you get this behavior with inheritance. A reference to a parent class (Shape) will manipulate child objects (Rectangles or Ellipses) without problems.

Interfaces were developed to get the same behavior in the context of component-based computing where you don't have access to the source code so you cannot use inheritance. The interface construct was the basis of all component communication in COM.

An interface is a contract to implement a set of methods in a clearly defined manner (method signatures). If you know that a class implements an interface you know that you can use any of the defined methods.

From that definition it is easy to imagine having a reference to an "interface instance" from which you can call any of the interface methods. So easy in fact that the framework provides just that.

Now suppose that instead of a Shape being a parent of Rectangle we just have a Shape interface that is implemented both by Rectangle and Ellipse. If I have a reference to a Rectangle object, I will be able to "cast" it to a reference to a Shape interface and pass it to the part of the program that knows only about "Shape objects".

This is exactly the same polymorphic behavior that we had via inheritance.

The class libraries rely heavily on interfaces and a clear understanding of the concept is essential.

An interesting problem with interfaces compared with inheritance is that you do not get a default implementation (virtual parent methods) so you have to recode everything. The techniques and tools do exist here but there is always some extra work to do. More on that with generics...

We have examples of using and building interfaces. Some interfaces of the System namespace are shown in the standard interfaces section.

Attributes

We now take a short break of our discussions on types to talk a little bit about attributes. First of all attributes are not types. They are elements of information that are added to a program element (assemblies, classes, method, etc.) to qualify it outside of the normal code associated with that element.

Those added "attributes" serves at doing manipulations of the underlying program element without having to modify the execution logic of the element.

Why would we ever want to manipulate program elements outside execution code? The short answer here is that object oriented concepts do not easily deal with what is known as cross-cutting concerns, or aspects of a program that apply to all or most classes. Examples of such aspects are security, persistence, serialization, etc. Instead of modifying every class to add serialization logic (which has nothing to do with business rules) you can add serialization attributes to the class to direct the serialization process of those classes without changing the business logic (execution code).

A number of functionality of the framework rely on attributes to add information to program elements. The attributes are kept by the compilation process and associated with their qualifying element in the assemblies. They are analyzed programmatically at run time using reflection to adjust the behavior of "cross-cutting" functionalities.

As for types we have System attributes (part of the framework) and Custom attributes (built by the developer). The development of Customs attributes will be treated in the reflection section. Until then we will limit ourselves with System attributes and focus on defining them and knowing how they will determine the behavior of framework.

The attributes usage section will give some example of how simple System attributes can be used.

Let's note here that attributes are not the only way to add "non-execution" information to a program to modify its behavior. XML configuration files for example can be used to specify parameters that will affect program execution. We will talk about those in the Configuration section of this book.

See MSDN for the discussion of attributes in C#.

Collections

A collection is a grouping of objects. The framework has many types of collections that cover most of the situations where you would process objects as a group. Knowing these collection types will save you the time to "re-code" equivalent logic and will keep your program more maintainable.

Unlike arrays collections come in many flavors each with its specific internal organization. Each type of collection is related to a specific type of problem. We will point out the types of problems when we give examples of each type of collections.

We have two sections with collections examples:

The major drawback of collections is that in "real life" objects that are grouped together usually have some characteristics in common (they are the same type, have a common parent type or support a common interface). So most of the time we know "more" about the objects than merely their organization. Collections do not allow us to use that knowledge to validate the objects passed to the collection or code logic applicable to all objects of the collection (without casting and exception handling that is).

Generic collections where introduced in version 2.0 of the framework. They solve this problem while keeping the other advantages of collections. For that reason they should be used whenever possible instead of "plain" collections.

Some external links on collections are GotDotNet and AspNetResources

See MSDN for a general discussion on arrays, collections and data structures.

Generics

Generic programming or the use of parameterized types is not an object oriented concept. In that sense Generics are a bit like attributes, they were added to main stream object-oriented platforms to take care of situations that are not easily covered by object-oriented techniques.

To start our discussion please read the following interesting linked article (annexes) that introduces the concept of generics in the context of generic collections. This external tutorial does the same.

The concept of Generics is interesting because it applies the concept of generalization to types. Types themselves are generalizations of objects (the basis of object-oriented programming). So here we start manipulating types, namely having types as parameters.

The actual type will be obtained when you substitute the parameter type with a specific type (For example when you declare a variable of that type).

// C#
List<int> myIntList = new List<int>()

'// VB.NET
Dim myIntList As New List(Of Integer)

In the .NET framework this substitution is done during the second compilation (the just-in-time compilation from CIL to machine code). Said differently, generics are supported by the CIL and are thus part of the framework itself, not of the language used (ex. C#).

For more coverage on generics see MSDN.

We have examples of using and building generic types.

For examples of generics collections see the using generic collections section.

Exceptions

This is how you throw a general exception:

// C#
throw new Exception("This is an exception.");

'// VB.NET
Throw New Exception("This is an exception.")

This is how you handle an exception:

// C#
try
{
   throw new Exception("This is an exception.");
}
catch (Exception e)
{
  Console.WriteLine(e.Message);
}

'// VB.NET
Try
  Throw New Exception("This is an exception.")
Catch ex As Exception
  Console.WriteLine(ex.Message)
End Try

Events and Delegates

For the “official” discussion of events and delegates see MSDN. What we will do here is a little more general discussion of the many concepts involved.

The first concept is delegation or the idea that part of the functionality of a class can be done “elsewhere” in the program, it can be delegated. The important benefit of delegation is that the “delegating” object does not have to know how the delegated functionality is actually implemented. One way to “delegate” is to define an interface. If an object has a reference to an interface it can delegate part of its functionality to the object implementing that interface without knowing much about that object.

.NET 2.0 defines another reference type called a delegate that implements the delegation pattern in a slightly different way. A delegate is a type that defines a reference to a single function that must have the same signature as the delegate definition. A signature is a description of the type of the function parameters and its return type. Like a class you can create an object of that type. The object created is a reference to a function that can be assigned (set the reference to a specific function), be passed as parameter or executed (the function that is referenced is actually executed). Unlike an interface, a delegate defines only one function and a delegate instance can be created directly (no need to have another class implementing the interface).

Most delegates in .NET derive from a multicast delegate. A multicast delegate is a delegate that keeps a list of references to functions having the same signature as the delegate definition instead of a single reference. You can add a reference to a multicast delegate using the += operator. When you execute a multicast delegate each function referenced is executed in turn.

If an object is from a class that implements a multicast delegate member, then if you have a reference to that object you can "add" to the multicast delegate a reference to a function of your choice. If the object decides to "execute" its delegate member then the function from which you added a reference will be executed.

This multicast delegate member is precisely what an event is in .NET. This is why events and delegates are almost always discussed together.

The procedure to define an event is:

  • You define a delegate type as a reference to functions having a specific signature
  • You add an Event member to a class and associate it with the delegate type you just define, this instantiate a multicast delegate associated with the event
  • When you have a reference to an object of the class you can add a reference to any method that has the same signature as the delegate type.
  • When the object raises the event, the associate multicast delegate is executed which triggers the execution of the referenced function.

Most of the time you will add a reference to one of your own method. When the referenced object fires its event it actually executes one of your methods without knowing it. This setup is an implementation of the publish / subscribe pattern. You subscribe to an event, signaling that you want to be informed when a specific "event" happens. Many object can subscribe to the same event. When the referenced object fires its event it "publishes" a message that the event has effectively happened in the form of a function call to all the "registered" functions.

So any class can define events. Many system classes define events to communicate to your code the fact that "something" happened in the executing environment (the mouse moved, a key was pressed, a message was received on a socket, etc.). Constructing a program that "waits" for events to happen and then react to them is called event programming. Most online applications and services follow this design. We will discuss in more details the way system events are catched in the section on multithreading.

For examples of events and delegates see this section.


Classes, Interfaces, and tools

Hello world example

    using System;
    using System.Collections.Generic;
    using System.Text;
namespace HelloWorldLab1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello world!");
            Console.WriteLine("Press ENTER to exit");
            Console.ReadLine();
        }
    }
}

Note: when you create a new console project in Visual studio, all the code is generated by default except for the 3 "Console" lines in the Main method. Just add those 3 lines and run the program.

We have discussed all the parts of that program except for the role of the Console which will be discussed in the input/output section (Stream). For now, lets say that it is a System class, in the System namespace (the "using System" instruction makes the "System." part of "System.Console.Writeline()" optional) and that the WriteLine() and ReadLine() methods write and read strings to and from the console.



Using System types

Exam objective: Manage data in a .NET Framework application by using the .NET Framework 2.0 system types.

(Refer System namespace)

Value types usage

Following are some "usage" oriented remarks about value types.

Value types contain the values they are assigned:

int a = 1;  // the variable "a" contains "1" of value type int

Value types can also be created by using the new keyword. Using the new keyword initializes the variable with the default value obtained from the type's default constructor:

int a = new int(); // using the default constructor via the new keyword
return a;          // returns "0" in the case of type Int.

Value types can be declared without being initialized, but they must be initialized to some value before being used:

int a;     // This is perfectly acceptable
return a;  // NOT acceptable!  You can't use "a" because "a" doesn't have a value!

Value types cannot equal null. .NET 2.0 provides a Nullable type to get around this limitation, which is discussed in the next section, but null is not a valid value for value types:

int a = null;  // Won't compile - throws an error.

If you copy a Value type to another Value type, the value is copied. Changing the value of the copy has no effect on the value of the original. The second is merely a copy of the first - they are in no way connected after assignment. This is fairly intuitive:

int var1 = 1;
int var2 = var1;  //the value of var1 (a "1" of type int) is copied to var2
var2 = 25;        // The "1" value in var2 is overwritten with "25"
Console.WriteLine("The value of var1 is {0}, the value of var2 is {1}", var1, var2);

Which would result in the output:

The value of var1 is 1, the value of var2 is 25

Changing the value of the copy (var2 in this instance) had no effect on the value of the original (var1). This is different from reference types which copy a reference to the value, not the value itself.

Value types cannot be derived from.

Value types as method parameters are passed by value by default. A copy of the value-type is made and the copy is passed to the method as a parameter. If the parameter is changed inside the method it will not affect the value of the original value type.


Clipboard

To do:
Eventually we could add an example showing the usage of some of the built-in value type: integer, floating point, logical, char and decimal and the value parameter passing of value types


Nullable type

See MSDN

A nullable type...

  • Is a generic type
  • Is an instance of System.Nullable struct.
  • Can only be declared on value types.
  • Is declared with System.Nullable<type> or the shorthand type? - the two are interchangeable.
System.Nullable<int> MyNullableInt;  // the long version 
int? MyNullableInt;                  // the short version
  • Accepts the normal range of values of the underlying type, as well as null.
bool? MyBoolNullable;  // valid values: true || false || null

Be careful with nullable booleans! In if, for, while or logical evaluation statements a nullable boolean will equate a null value with false—it will not throw an error.

Methods: T GetValueOrDefault() & T GetValueOrDefault(T defaultValue)
Returns the stored value or the default value if the stored value is set to null.

Properties: HasValue & Value
Nullable types have two read only properties: HasValue and Value.

HasValue is a boolean property that returns true if Value != null. It provides a means to check your type for a non-null value before using it where you might throw an error:

 int? MyInt = null;
 int MyOtherInt;
 MyOtherInt = MyInt.Value + 1;    // Error! You can't add null + 1!!
 if (MyInt.HasValue) MyOtherInt = MyInt.Value + 1; // This is a better way.

Value returns the value of your type, null or otherwise.

int? MyInt = 27;
if (MyInt.HasValue) return MyInt.Value;  // returns 27.
MyInt = null;
return MyInt; // returns null.

Wrapping / Unwrapping

Wrapping is the process of packaging a value m from a non-nullable type N to a nullable type N? via the expression new N?(m)

Unwrapping is the process of evaluating a nullable type N? for instance m as type N or NULL and is performed via the 'Value' property (e.g. m.Value).

Note: Unwrapping a null instance generates the exception System.InvalidOperationException

The ?? Operator (aka the Null Coalescing Operator)

While not for use solely with Nullable types, the ?? operator proves very useful when you want to use a default value instead of a null value. The ?? operator returns the left operand of a statement if not null, otherwise it returns the right operand.

int? MyInt = null;
return MyInt ?? 27;  // returns 27, since MyInt is null

For more information see the blog entry by R. Aaron Zupancic on the ?? Operator

Building a value type

Building a value type must be very simple. The following example defines a custom "point" structure with only 2 double members. See boxing and unboxing for a discussion of implicit conversion of value types to reference types.

C# Code sample

Building and using a custom value type (struct)

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace ValueTypeLab01
   {
       class Program
       {
           static void Main(string[] args)
           {
               MyPoint p;
               p.x = 3.2;
               p.y = 14.1;
               Console.WriteLine("Distance from origin: " + Program.Distance(p));
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // method where MyPoint is passed by value
           public static double Distance(MyPoint p)
           {
               return Math.Sqrt(p.x * p.x + p.y * p.y);
           }
       }
       // MyPoint is a struct (custom value type) representing a point
       public struct MyPoint
       {
           public double x;
           public double y;
       }
   }

Using a user-defined value type

The above example can be used here. Note that the p variable does not have to be initialized with the new operator.

Using enumerations

The following sample shows simple uses of the System enumeration DayOfWeek. The code is much simpler to read than testing for an integer value representing a day. Note that using ToString() on an enum variable will give the string representation of the value (ex. “Monday” instead of “1”).

The possible values can be listed using Reflection. See that section for details.

For a discussion of the Enum class see MSDN

There is a special type of enumeration called a flags enumeration. The exam objectives do not mention it specifically. See MSDN if you are interested.

C# Sample

Simple use of enumerations

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace EnumLab01
   {
       class Program
       {
           static void Main(string[] args)
           {
               DayOfWeek day = DayOfWeek.Friday;
               if (day == DayOfWeek.Friday)
               {
                   Console.WriteLine("Day: {0}", day);
               }
               DayOfWeek day2 = DayOfWeek.Monday;
               if (day2 < day)
               {
                   Console.WriteLine("Smaller than Friday");
               }
               switch (day)
               {
                   case DayOfWeek.Monday:
                       Console.WriteLine("Monday processing");
                       break;
                   default:
                       Console.WriteLine("Default processing");
                       break;
               }
               int i = (int)DayOfWeek.Sunday;
               Console.WriteLine("Int value of day: {0}", i);
               // Finishing
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
       }
   }

Building an enumeration

Building a custom enumeration is pretty straightforward as shown by the following example.

C# Sample

Declaring a simple enumeration

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace EnumLab02
   {
       class Program
       {
           public enum MyColor
           {
               None = 0,
               Red,
               Green,
               Blue
           }
           static void Main(string[] args)
           {
               MyColor col = MyColor.Green;
               Console.WriteLine("Color: {0}", col);
               // Finishing
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
       }
   }

Using reference types

Reference types are more commonly referred to as objects. Classes, Interfaces and Delegates are all reference types, as well as the built-in reference types System.Object and System.String. Reference types are stored in managed Heap memory.

Unlike Value types, reference types can be assigned the value null.

Copying a reference type copies a reference that points to the object, not a copy of the object itself. This can seem counter-intuitive at times, since changing a copy of a reference will also change the original.

A Value type stores the value it is assigned, plain and simple - but a Reference type stores a pointer to a location in memory (on the heap). Think of the heap as a bunch of lockers and the Reference type holds the locker number (there are no locks in this metaphor). Copying a Reference type is like giving someone a copy of your locker number, rather than a copy of its contents. Two Reference types that point to the same memory is like two people sharing the same locker - both can modify its content:

C# Code sample

Example of using Reference types

public class Dog
{
  private string breed;
  public string Breed { get {return breed;} set {breed = value;} }
  
  private int age;
  public int Age { get {return age;} set {age = value;} }
  
  public override string ToString()
  {
    return String.Format("is a {0} that is {1} years old.", Breed, Age);
  }
  
  public Dog(string dogBreed, int dogAge)
  {
    this.breed = dogBreed;
    this.age = dogAge;
  }
}

public class Example()
{
   public static void Main()
   {
     Dog myDog = new Dog("Labrador", 1);    // myDog points to a position in memory.
     Dog yourDog = new Dog("Doberman", 3);  // yourDog points to a different position in memory.

     yourDog = myDog; // both now point to the same position in memory, 
                    // where a Dog type has values of "Labrador" and 1
   
     yourDog.Breed = "Mutt";
     myDog.Age = 13; 

     Console.WriteLine("Your dog {0}\nMy dog {1}", yourDog.ToString(), myDog.ToString());
   }
}

Since the yourDog variable and the the myDog variable both point to the same memory store, the output of which would be:

Your dog is a Mutt that is 13 years old.
My dog is a Mutt that is 13 years old.

As a practice for manipulating reference types you may want to work with the String and StringBuilder classes. We have put these with the text manipulation section but manipulating strings is a basic operation of almost all programs.

Using and building arrays

See MSDN for reference information.

Using classes

Building a custom class

Using interfaces

Building a custom interface

Using attributes

Using generic types

The use of the four major categories of System Generic Types will mainly be demonstrated elsewhere in this book:

  • The nullable type was discussed above
  • A whole section follows on Generic collections
  • The generic event handler will be discussed in the Event / Delegate section.
  • The generic delegates will also be discussed in the Event / Delegate section as well as in the Generic collections section (Comparer class).

If you copy the next very simple example in Visual Studio and try to add something other than an int to the list the program will not compile. This demonstrates the strong typing capability of generics.

Simple use of generics (C#)

Very simple use of generic

   using System;
   using System.Collections.Generic;
   namespace GenericsLab01
   {
       class Program
       {
           static void Main(string[] args)
           {
               List<int> myIntList = new List<int>();
               myIntList.Add(32);
               myIntList.Add(10); // Try to add something other than an int 
                                  // ex. myIntList.Add(12.5);
               foreach (int i in myIntList)
               {
                   Console.WriteLine("Item: " + i.ToString());
               }
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
       }
   }

You can use List<string> instead of List<int> and you will get a list of strings for the same price (you are using the same List(T) class).

Building generics

The programming of a custom generic collection was shown in the article mentioned in the topics discussion.

Here we have an example of a Generic Function. We use the trivial problem of swapping two references. Although very simple we still see the basic benefits of Generics:

  • We don't have to recode a swap function for every type
  • The generalization does not cost us the strong typing (try swapping an int and a string, it wont compile)
Simple custom generic function (C#)

Simple custom generic function

   using System;
   using System.Collections.Generic;
   using System.Text;
   namespace GenericsLab03
   {
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Swap strings
               string str1 = "First string";
               string str2 = "Second string";
               pgm.swap<string>(ref str1, ref str2);
               Console.WriteLine(str1);
               Console.WriteLine(str2);
               // Swap integers
               int int1 = 1;
               int int2 = 2;
               pgm.swap<int>(ref int1, ref int2);
               Console.WriteLine(int1);
               Console.WriteLine(int2);
               // Finish with wait
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // Swapping references
           void swap<T>(ref T r1,ref T r2)
           {
               T r3 = r1;
               r1 = r2;
               r2 = r3;
           }
       }
   }


Next step is to present an example including a generic interface, a generic class that implements that generic interface and a class derived from that generic class. The sample also uses interface and derivation constraints.

This is another simple problem involving employees and suppliers which have nothing in common except that they can request payment to a "payment handler" (see visitor pattern).

The problem is to know where to put the logic if you have specific processing to do for a certain kind of payment just for employees. There are myriads of ways to solve that problem but the use of generics make the following sample clean, explicit and strongly typed.

The other nice thing is that it has nothing to do with containers or collections where you will find almost all of generic samples.

Please note that the EmployeeCheckPayment<T> class derives from CheckPayment<T> giving a stronger constraint on the type parameter T (must be employee not just implement IPaymentInfo). That gives us the to opportunity to have access (in its RequestPayment method) to all payment logic (from the base class) at the same time as all employee public interface (thru the sender method parameter) and that without having to do any cast.

Custom generic interface and class (C#)

Custom generic interface and class

   using System;
   using System.Collections.Generic;
   using System.Text;
   namespace GennericLab04
   {
       class Program
       {
           static void Main(string[] args)
           {
               // Pay supplier invoice
               CheckPayment<Supplier> checkS = new CheckPayment<Supplier>();
               Supplier sup = new Supplier("Micro", "Paris", checkS);
               sup.InvoicePayment();
               // Produce employee paycheck
               CheckPayment<Employee> checkE = new EmployeeCheckPayment<Employee>();
               Employee emp = new Employee("Jacques", "Montreal", "bigboss", checkE);
               emp.PayTime();
               // Wait to finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
       }
       // Anything that can receive a payment must implement IPaymentInfo
       public interface IPaymentInfo
       {
           string Name { get;}
           string Address { get;}
       }
       // All payment handlers must implement IPaymentHandler
       public interface IPaymentHandler<T> where T:IPaymentInfo 
       {
           void RequestPayment(T sender, double amount);
       }
       // Suppliers can receive payments thru their payment handler (which is given by an  object factory)
       public class Supplier : IPaymentInfo
       {
           string _name;
           string _address;
           IPaymentHandler<Supplier> _handler;
           public Supplier(string name, string address, IPaymentHandler<Supplier> handler)
           {
               _name = name;
               _address = address;
               _handler = handler;
           }
           public string Name { get { return _name; } }
           public string Address { get { return _address; } }
           public void InvoicePayment()
           {
               _handler.RequestPayment(this, 4321.45);
           }
       }
       // Employees can also receive payments thru their payment handler (which is given by an  object factory)
       // even if they are totally distinct from Suppliers
       public class Employee : IPaymentInfo
       {
           string _name;
           string _address;
           string _boss;
           IPaymentHandler<Employee> _handler;
           public Employee(string name, string address, string boss, IPaymentHandler<Employee> handler)
           {
               _name = name;
               _address = address;
               _boss = boss;
               _handler = handler;
           }
           public string Name { get { return _name; } }
           public string Address { get { return _address; } }
           public string Boss { get { return _boss; } }
           public void PayTime()
           {
               _handler.RequestPayment(this, 1234.50);
           }
       }
       // Basic payment handler
       public class CheckPayment<T>  : IPaymentHandler<T> where T:IPaymentInfo
       {
           public virtual void RequestPayment (T sender, double amount) 
           {
               Console.WriteLine(sender.Name);
           }
       }
       // Payment Handler for employees with supplementary logic
       public class EmployeeCheckPayment<T> : CheckPayment<T> where T:Employee
       {
           public override void RequestPayment(T sender, double amount)
           {
               Console.WriteLine("Get authorization from boss before paying, boss is: " + sender.Boss);
	            base.RequestPayment(sender, amount);
           }
       }
   }

Exception classes

Some links to MSDN:

  • Exceptions and exception handling - MSDN
  • Handling and throwing exceptions - MSDN
  • Exception Hierarchy - MSDN
  • Exception Class and Properties - MSDN

Boxing and unboxing

See MSDN

All types derive directly or indirectly from System.Object (including value types by the way of System.ValueType). This allows the very convenient concept of a reference to "any" object but poses some technical concerns because value types are not "referenced". Comes boxing and unboxing.

Boxing and unboxing enable value types to be treated as objects. Boxing a value type packages it inside an instance of the Object reference type. This allows the value type to be stored on the garbage collected heap. Unboxing extracts the value type from the object. In this example, the integer variable i is boxed and assigned to object o:

int i = 123;
object o = (object) i;  // boxing

Please also note that it is not necessary to explicitly cast an integer to an object (as shown in the example above) to cause the integer to be boxed. Invoking any of its methods would also cause it to be boxed on the heap (because only the boxed form of the object has a pointer to a virtual method table):

int i=123;
String s=i.toString(); //This call will cause boxing

There is also a third way in which a value type can be boxed. That happens when you pass a value type as a parameter to a function that expects an object. Let's say there is a function prototyped as:

void aFunction(object value)

Now let's say from some other part of your program you call this function like this:

int i=123;
aFunction(i); //i is automatically boxed

This call would automatically cast the integer to an object, thus resulting in boxing.

The object o can then be unboxed and assigned to integer variable i:

o = 123;
i = (int) o;  // unboxing

Performance of boxing and unboxing

In relation to simple assignments, boxing and unboxing are computationally expensive processes. When a value type is boxed, an entirely new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally.

TypeForwardedToAttribute Class

See MSDN

For a discussion of TypeForwardToAttribute in the CLR see MSDN
Other possible links: Marcus' Blog, NotGartner


Using Collections

Exam objective: Manage a group of associated data in a .NET Framework application by using collections.

(Refer System.Collections namespace - MSDN)

ArrayList class

see MSDN

The ArrayList class is used for arrays whose size will dynamically increase as required. An ArrayList is not necessarily sorted.

using System;
using System.Collections;
public class Demo {
    public static void Main() {
        ArrayList myArrayList = new ArrayList();
        myArrayList.Add("Testing");
        myArrayList.Add("1...2...3");
    }
}
Collection interfaces
ICollection interface and IList interface
ICollection interface - MSDN
The ICollection interface is the base interface for classes in the System.Collections namespace.
The ICollection interface extends IEnumerable; IDictionary and IList are more specialized interfaces that extend ICollection. An IDictionary implementation is a collection of key/value pairs, like the Hashtable class. An IList implementation is a collection of values and its members can be accessed by index, like the ArrayList class.
Some collections that limit access to their elements, such as the Queue class and the Stack class, directly implement the ICollection interface.
If neither the IDictionary interface nor the IList interface meet the requirements of the required collection, derive the new collection class from the ICollection interface instead for more flexibility.
The following tables list the members exposed by the ICollection type.
Public Properties
  Count - Gets the number of elements contained in the ICollection.  
  IsSynchronized - Gets a value indicating whether access to the ICollection is synchronized (thread safe).  
  SyncRoot - Gets an object that can be used to synchronize access to the ICollection.  

Public Methods
  CopyTo - Copies the elements of the ICollection to an Array, starting at a particular Array index.   
IList interface - MSDN
IComparer interface, IEqualityComparer interface, and IKeyComparer interface
IComparer interface - MSDN
IEqualityComparer interface - MSDN
IKeyComparer interface - IKeyComparer does not exist in .Net 2.0
IDictionary interface and IDictionaryEnumerator interface
IDictionary interface - MSDN
IDictionaryEnumerator interface - MSDN
IEnumerable interface and IEnumerator interface - MSDN and MSDN
C# code sample

IEnumerator sample

public class Person
{
   public Person(string fName, string lName)
   {
       this.firstName = fName;
       this.lastName = lName;
   }
   public string firstName;
   public string lastName;
}
public class PeopleEnum : IEnumerator
{
   public Person[] _people;
   //Enumerators are positioned before the first element
   //until the first MoveNext() call.
   int position = -1;
   public PeopleEnum(Person[] list)
   {
       _people = list;
   }
   public bool MoveNext()
   {
       position++;
       return (position < _people.Length);
   }
   public void Reset()
   {
       position = -1;
   }
   public object Current
   {
       get
       {
           try
           {
               return _people[position];
           }
           catch (IndexOutOfRangeException)
           {
               throw new InvalidOperationException();
           }
       }
   }
}
public class People : IEnumerable
{
   private Person[] _people;
   public People(Person[] pArray)
   {
       _people = new Person[pArray.Length];
       for (int i = 0; i < pArray.Length; i++)
       {
           _people[i] = pArray[i];
       }
   }
   public IEnumerator GetEnumerator()
   {
       return new PeopleEnum(_people);
   }
}

Write down a handler for Practicing the above code.

protected void lnkEnumerator_Click(object sender, EventArgs e)
   {
       Person[] peopleArray = new Person[] {
           new Person("Irfan", "Akhtar"),
           new Person("Hammad", "Anwar"),
           new Person("Majid", "Aalim")     };
       PeopleEnum Prson = new PeopleEnum(peopleArray);
  • One way of using IEnumerator.
 while (Prson.MoveNext () )
 {
       Person P = (Person)Prson.Current;
       Response.Write("First Name : " + P.firstName + ", Last Name : " + P.lastName);
 }


  • One way of using IEnumerable.
People peopleList = new People(peopleArray);
foreach (Person p in peopleList)
    Response.Write("First Name : " + p.firstName + ", Last Name : " + p.lastName);
IHashCodeProvider interface - MSDN - Interface is now obsolete (as of .NET 2.0)

Iterators

See MSDN

An iterator is effectively a lightweight version of the IEnumerable interface. It is primarily used with foreach statements.
You will normally implement the GetEnumerator method of the IEnumerable interface.
public class Colors : System.Collections.IEnumerable
{
    string[] colors = { "Red", "Green", "Blue" };
    public System.Collections.IEnumerator GetEnumerator()
    {
        for (int i = 0; i < colors.Length; i++)
        {
            yield return colors[i];
        }
    }
}
This enables the class to be accessed using a standard foreach statement. A class is not restricted to implementing only a single iterator. Multiple iterators can be supplied, for example to enable iteration in both ascending and descending order of a list. To call a named iterator, use the following syntax:
foreach (int i in myList.NamedIterator())
{
    System.Console.WriteLine(i);
}
The yield statement marks a point where execution of a iterator will resume on a subsequent iteration. This can be used to supply multiple yield statements:
public System.Collections.IEnumerator GetEnumerator()
{
    yield return "Statement returned on iteration 1";
    yield return "Statement returned on iteration 2";
}
To end the iteration programmatically, use the
yield break;
statement.

Hashtable class - MSDN

Used to represent a collection of key/value pairs.

CollectionBase class and ReadOnlyCollectionBase class

CollectionBase class - MSDN
ReadOnlyCollectionBase class -MSDN

DictionaryBase class and DictionaryEntry class

DictionaryBase class - MSDN
DictionaryEntry structure - MSDN

Comparer class - MSDN

Queue class - MSDN

SortedList class - MSDN

BitArray class - MSDN

Stack class - MSDN

<noinclide> </noinclude>


Using generic collections

Exam objective: Improve type safety and application performance in a .NET Framework application by using generic collections.

(Refer System.Collections.Generic namespace MSDN )

Collection.Generic interfaces

Generic IComparable interface - MSDN
Note that IComparable<T> is a member of the System namespace.
You use this interface when you create a class and you want it to be used with generic types that support ordering (ex. SortedList<T> or List<T>.Sort()) without having to specify a comparer object. The only method of IComparable<T> is CompareTo<T>(T other). There is an example on MSDN.
The following example implements IComparable<T> for a custom made Point class. The example uses a List<T> instead of a SortedList<T> or OrderedDictionnary<T> because the comparaison is done based on the distance of the points from the origin which can give the same value for many points.
Simple use IComparable<T> (C#)

Simple use IComparable<T> (C#)

   using System;
   using System.Collections.Generic;
   using System.Text;
   namespace GenericsLab05
   {
       class Program
       {
           static void Main(string[] args)
           {
               List<Point> lst = new List<Point>();
               lst.Add(new Point(-2, -2));
               lst.Add(new Point(1, 1));
               lst.Add(new Point(2, 2));
               // Sort uses IComparable of Point
               lst.Sort();
               foreach (Point pt in lst)
               {
                   Console.WriteLine(pt.ToString());
               }
               // Wait to finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
       }
       // This is out custom version of a point
       public struct Point : IComparable<Point>
       {
           public double x;
           public double y;
           public Point(double px, double py)
           {
               x = px;
               y = py;
           }
           // Comparaison done based on distance from origin
           public int CompareTo(Point other)
           {
               return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2)).CompareTo
                   (Math.Sqrt(Math.Pow(other.x, 2) + Math.Pow(other.y, 2)));
           }
           public override string ToString()
           {
               return "(" + x.ToString() + "," + y.ToString() + ")";
           }
       }
   }
Generic ICollection interface and Generic IList interface
Generic ICollection interface - MSDN
Generic IList interface - MSDN
Generic IComparer interface and Generic IEqualityComparer interface
Generic IComparer interface - MSDN
Generic IEqualityComparer interface - MSDN
Generic IDictionary interface - MSDN
Generic IEnumerable interface and Generic IEnumerator interface
Generic IEnumerable interface - MSDN
see also ONDotnet
Generic IEnumerator interface - MSDN
IHashCodeProvider interface - MSDN - Interface is now obsolete (as of .NET 2.0)
Generic Dictionary
Generic Dictionary class and Generic Dictionary.Enumerator structure
Generic Dictionary class - MSDN
Generic Dictionary.Enumerator structure - MSDN
Generic Dictionary.KeyCollection class and Dictionary.KeyCollection.Enumerator structure
Generic Dictionary.KeyCollection class - MSDN
Dictionary.KeyCollection.Enumerator structure - MSDN
Generic Dictionary.ValueCollection class and Dictionary.ValueCollection.Enumerator structure
Generic Dictionary.ValueCollection class - MSDN
Dictionary.ValueCollection.Enumerator structure - MSDN

Generic Comparer class and Generic EqualityComparer class

Generic Comparer class - MSDN
The Comparer<T> class serves as a base class to easily implement the IComparer<T> interface.
The example is the same then for the IComparable<T> except that now a Comparer<T> derived object is given to the List<T>.Sort() method instead of implementing the IComparable<T> interface on Point.
This way of preceding has 2 advantages:
  • It can be used even if you dont have access to the source code of Point
  • You can have more than one Comparer derived class for the same Point class
Custom Comparer<T> (C#)

Custom Comparer<T> (C#)

   using System;
   using System.Collections.Generic;
   using System.Text;
   namespace GenericsLab06
   {
       class Program
       {
           static void Main(string[] args)
           {
               List<Point> lst = new List<Point>();
               lst.Add(new Point(-2, -2));
               lst.Add(new Point(1, 1));
               lst.Add(new Point(2, 2));
               // Sort uses IComparable of Point
               lst.Sort(new DistanceComparer());
               foreach (Point pt in lst)
               {
                   Console.WriteLine(pt.ToString());
               }
               // Wait to finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
       }
       // This is out custom version of a point
       public struct Point 
       {
           public double x;
           public double y;
           public Point(double px, double py)
           {
               x = px;
               y = py;
           }
           public override string ToString()
           {
               return "(" + x.ToString() + "," + y.ToString() + ")";
           }
       }
       // Derive from base comparer class to implement IComparer<T>
       public class DistanceComparer : Comparer<Point>
       {
           public override int Compare(Point p1, Point p2)
           {
               return Math.Sqrt(Math.Pow(p1.x, 2) + Math.Pow(p1.y, 2)).CompareTo
                   (Math.Sqrt(Math.Pow(p2.x, 2) + Math.Pow(p2.y, 2)));
           }
       }
   }
Generic EqualityComparer class - MSDN

Generic KeyValuePair structure

see MSDN

Generic List class, Generic List.Enumerator structure, and Generic SortedList class

Generic List class - MSDN
A generic list class instance is simply declared using the List<T> syntax where T is the specific type.
Generic List.Enumerator structure - MSDN
Generic SortedList class - MSDN

Generic Queue class and Generic Queue.Enumerator structure

Generic Queue class - MSDN
Generic Queue.Enumerator structure - MSDN

Generic SortedDictionary class

See MSDN
For differences between SortedList and SortedDictionary are explained see MSDN

Generic LinkedList

A Generic Linked List represents a doubly linked list and is a general-purpose linked list. It supports enumerators and implements the ICollection interface, consistent with other classes in the .NET Framework.
Generic LinkedList class - MSDN
Generic LinkedList.Enumerator structure - MSDN
Generic LinkedListNode class - MSDN

Generic Stack class and Generic Stack.Enumerator structure

Generic Stack class - MSDN
Generic Stack.Enumerator structure - MSDN



Using specialized collections

Exam objective: Manage data in a .NET Framework application by using specialized collections.

(Refer System.Collections.Specialized namespace)

Specialized String classes

StringCollection class - MSDN
StringDictionary class - MSDN
StringEnumerator class - MSDN
Specialized Dictionary classes
HybridDictionary class - MSDN
IOrderedDictionary interface and OrderedDictionary class
IOrderedDictionary Interface - MSDN
OrderedDictionary class - MSDN
ListDictionary class - MSDN

Named collections

NameObjectCollectionBase class - MSDN
NameObjectCollectionBase.KeysCollection class - MSDN
NameValueCollection class - MSDN

CollectionsUtil class

CollectionsUtil class - MSDN

BitVector32 structure and BitVector32.Section structure

BitVector32 structure - MSDN
BitVector32.Section structure - MSDN

Standard interfaces

Exam objective: Implement .NET Framework interfaces to cause components to comply with standard contracts.

(Refer System namespace)

IComparable interface - MSDN

The IComparable interface defines a comparison method that a value type or class implements to create a type-specific comparison method

IDisposable interface - MSDN

The IDispose interface can be used to explicitly release unmanaged resources in custom classes. The consumer of an object can call this method when the object is no longer needed.
The .Net garbage collector releases memory allocated to managed objects when they are no longer used, however, it is not possible to predict when garbage collection will occur and it has no knowledge of unmanaged resources such as window handles, or open files and streams.

IConvertible interface - MSDN

ICloneable interface - MSDN

INullableValue interface - MSDN

IEquatable interface - MSDN

IFormattable interface - MSDN



Using events and delegates

Exam objectives: Control interactions between .NET Framework application components by using events and delegates.

(Refer System namespace)

Delegate class - MSDN

Delegates hold pointers to one or more functions and invoke them as needed.
One common use of delegates is for event handling. A class that raises an event does not know what objects or methods want to receive the event, so an intermediary or pointer mechanism is needed between the object raising the event and the object(s) receiving the event. Delegates can be used as function pointers to accomplish this.
A delegate is a class, but unlike a regular class it has a signature. In the .Net framework you just declare the delegate and the CLR handles the implementation of the class.
   //delegate declaration
   public delegate void AlarmEventHandler(object sender,EventArgs e);
The first complete example just declare a delegate type, then declare a variable of that type, assign a function to it and execute the delegate variable which has the effect of executing the function.
C# sample

Simple delegate

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace DelegateLab01
   {
       // declare the delegate type
       public delegate int IntOperDel(int i);
       //
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Assign the delegate
               IntOperDel deleg = pgm.Increment;
               // Executing the delegate
               int res = deleg(32);
               Console.WriteLine("First value: " + res.ToString());
               // Second assign
               deleg = pgm.Decrement;
               // Second execution
               res = deleg(32);
               Console.WriteLine("First value: " + res.ToString());
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // First function to be assigned to the delegate
           public int Increment(int n)
           {
               return n + 1;
           }
           // Second function to be assigned to the delegate
           public int Decrement(int n)
           {
               return n - 1;
           }
       }
   }
The second delegate example implement the concept of a callback function. A function is called with a delegate as an argument. When it executes the delegate it has no knowledge of exactly what function is executed. Part of its behavior is delegated to the function passed as a parameter (thru the delegate).
C# sample

Callback delegate

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace DelegateLab02
   {
       // declare the delegate type
       public delegate int IntOperDel(int i);
       //
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Assign the delegate
               IntOperDel deleg = pgm.Increment;
               // Calling a function that will execute de delegate
               // as part of its own logic
               pgm.ExecuteCallBack(deleg);
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // Function to be assigned to a delegate
           public int Increment(int n)
           {
               return n + 1;
           }
           // Function called with a delegate as parameter
           public void ExecuteCallBack(IntOperDel deleg)
           {
               int res = deleg(32);
               Console.WriteLine("Result from executing the callback: " + res.ToString());
           }
       }
   }
The third delegate example uses a delegate member to produce the same pattern as an event. Note that executing the delegate member without assigning at least one function will cause an exception. Also assigning 2 functions with the += operator will execute the 2 functions when the delegate is executed. If the delegate has a return code, the return value of the last executed function will be returned.
C# sample

Delegate member

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace DelegateLab03
   {
       // declare the delegate type
       public delegate void IntOperDel(int i);
       //
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Use += oper to assign functions to the delegate
               pgm.delMember += pgm.Increment;
               pgm.delMember += pgm.Decrement;
               // Calling some member function that will execute the delegate
               pgm.ExecuteSomething();
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // First function to be assigned to a delegate
           public void Increment(int n)
           {
               int res = n + 1;
               Console.WriteLine("Inside increment function: " + res.ToString());
           }
           // Second function to be assigned to a delegate
           public void Decrement(int n)
           {
               int res = n - 1;
               Console.WriteLine("Inside decrement function: " + res.ToString());
           }
           // Class member of the delegate type
           public IntOperDel delMember;
           // Function called to execute the delegate member (raise the "event")
           public void ExecuteSomething()
           {
               this.delMember(32);
           }
       }
   }
The fourth example is the basic example of an event. It is exactly as the third example with the event keyword added to the member declaration and a test before calling the event because of the exception thrown on an "empty" event. This example shows clearly that an event is nothing more then a multicast delegate.
C# sample

Event member

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace DelegateLab04
   {
       // declare the delegate type
       public delegate void IntOperDel(int i);
       //
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Use += oper to assign functions to the delegate
               pgm.delMember += pgm.Increment;
               pgm.delMember += pgm.Decrement;
               // Calling some member function that will execute the delegate
               pgm.ExecuteSomething();
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // First function to be assigned to a delegate
           public void Increment(int n)
           {
               int res = n + 1;
               Console.WriteLine("Inside increment function: " + res.ToString());
           }
           // Second function to be assigned to a delegate
           public void Decrement(int n)
           {
               int res = n - 1;
               Console.WriteLine("Inside decrement function: " + res.ToString());
           }
           // Class member event of the delegate type
           public event IntOperDel delMember;
           // Function called to execute the delegate member (raise the "event")
           public void ExecuteSomething()
           {
               if (this.delMember != null)
                   this.delMember(32);
           }
       }
   }
Executing the functions associated with an event is called raising the event.
The functions associated with the event are called event handlers

EventArgs class - MSDN

By convention an event uses a delegate that returns void and take 2 arguments:
  • an object of type System.Object that contains a reference to the object that raised the event.
  • an object from a class derived from EventArgs that contains the data passed from the object that raised the event to the event handlers.
The EventArgs class does not contain any data by itself.
So an event with no data will use a delegate of the form
public delegate void DelegateTypeName (object sender, EventArgs e)
This simple event example is the same as the last one with the IntEventArgs class that serves for passing the int argument to the event handler and all the parameters changed to follow the calling convention for events.
C# sample

Event with delegate that follows the calling convention

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace EventLab01
   {
       // the class containing the event data passed to the event handler
       public class IntEventData : EventArgs
       {
           public int IntParm = 0;
           // constructor
           public IntEventData(int i)
           {
               IntParm = i;
           }
       }
       // the delegate type
       public delegate void IntOperDel(object sender, IntEventData e);
       //
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Use += oper to assign functions to the delegate
               pgm.delMember += pgm.Increment;
               pgm.delMember += pgm.Decrement;
               // Calling some member function that will execute the delegate
               pgm.ExecuteSomething();
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // First function to be assigned to a delegate
           public void Increment(object sender, IntEventData e)
           {
               int res = e.IntParm + 1;
               Console.WriteLine("Inside increment function: " + res.ToString());
           }
           // Second function to be assigned to a delegate
           public void Decrement(object sender, IntEventData e)
           {
               int res = e.IntParm - 1;
               Console.WriteLine("Inside decrement function: " + res.ToString());
           }
           // Class member event of the delegate type
           public event IntOperDel delMember;
           // Function called to execute the delegate member (raise the "event")
           public void ExecuteSomething()
           {
               if (this.delMember != null)
                   this.delMember(this, new IntEventData(32));
           }
       }
   }

EventHandler delegates - MSDN and MSDN

There are two special delegates defined in the System namespace to help you with the events declarations.
The first is the EventHandler delegate. It passes no data. An event that passes no data can be declared as:
public event EventHandler EventName
without having to declare a custom delegate.
This is the usual way to declare an event that passes no data.
C# sample

Event with EventHandler delegate

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace EventLab03
   {
       //
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Use += oper to assign functions to the delegate
               pgm.delMember += pgm.Increment;
               pgm.delMember += pgm.Decrement;
               // Calling some member function that will execute the delegate
               pgm.ExecuteSomething();
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // First function to be assigned to the event
           public void Increment(object sender, EventArgs e)
           {
               int res = 32 + 1;
               Console.WriteLine("Inside increment function: " + res.ToString());
           }
           // Second function to be assigned to the event
           public void Decrement(object sender, EventArgs e)
           {
               int res = 32 - 1;
               Console.WriteLine("Inside decrement function: " + res.ToString());
           }
           // Class member event of the delegate type
           public event EventHandler delMember;
           // Function called to execute the delegate member (raise the "event")
           public void ExecuteSomething()
           {
               if (this.delMember != null)
                   this.delMember(this, null);
           }
       }
   }
The second is the EventHandler<T> generic delegate where T is a type derived from EventArgs
public event EventHandler<T> EventName
again no need to declare a custom delegate type.
This is the usual way to declare an event that passes data to the event handlers.
Note that in this case you still have to declare the type T derived from EventArgs.
C# sample

Event utilizing EventHandler<T>

   using System;
   using System.Collections.Generic;
   using System.Text;
   //
   namespace EventLab02
   {
       // the class containing the event data passed to the event handler
       public class IntEventData : EventArgs
       {
           public int IntParm = 0;
           // constructor
           public IntEventData(int i)
           {
               IntParm = i;
           }
       }
       //
       class Program
       {
           static void Main(string[] args)
           {
               Program pgm = new Program();
               // Use += oper to assign functions to the delegate
               pgm.delMember += pgm.Increment;
               pgm.delMember += pgm.Decrement;
               // Calling some member function that will execute the delegate
               pgm.ExecuteSomething();
               // Wait for finish
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
           // First function to be assigned to a delegate
           public void Increment(object sender, IntEventData e)
           {
               int res = e.IntParm + 1;
               Console.WriteLine("Inside increment function: " + res.ToString());
           }
           // Second function to be assigned to a delegate
           public void Decrement(object sender, IntEventData e)
           {
               int res = e.IntParm - 1;
               Console.WriteLine("Inside decrement function: " + res.ToString());
           }
           // Class member event of the delegate type
           public event EventHandler<IntEventData> delMember;
           // Function called to execute the delegate member (raise the "event")
           public void ExecuteSomething()
           {
               if (this.delMember != null)
                   this.delMember(this, new IntEventData(32));
           }
       }
   }
This concludes the basic examples for events and delegates.



Services, threading, and application domains

Exam objective: Implementing service processes, threading, and application domains in a .NET Framework application

Topics

Services

The term service stands here for a Windows service. The basic definition of a Windows service is a long-running process that does not require a user interface. Why would you need a long-running process that does not require a user interface? Essentially two reasons:

  • Doing maintenance tasks that do not need user intervention. A backup software for example will regularly check the backup schedule and execute the different backup tasks when needed. No user interface is needed for that.
  • Responding to requests that come from other processes or from the operating system. An http server such as IIS (Windows component that process web requests) will receive http requests coming from client browsers and produce responses (html pages) to those same browsers. A database process is another good example. Again the http server does not need a user interface because the interface with the client is managed by the client browser component.

The exam objectives concerning services are very basic and touch the first problems that you will encounter when dealing with them:

  • Since the service has no user interface then who will start and stop it? The answer is that the operating system executes the services directly but you have to ‘’register’’ your service to let the system know where it is and what to do with it (this is the installation process)
  • A process with a user interface essentially waits for events coming from the user. How does a service ‘’work’’ in the absence of a message pump (the technique to get user input in a typical online application)?
  • If the service does a user interface function it will “hang” waiting for a non-existent user. How can you avoid that?

The more important and complicated design issues are not covered by this exam and will be treated by the enterprise development exam.

Multithreading


Clipboard

To do:
Description of multithreading support in .NET


Application Domain


Clipboard

To do:
Short description of the application domain in the CLI


Classes, Interfaces, and tools

Implement, install, and control a service

Exam objective: Implement, install, and control a service

(Refer System.ServiceProcess namespace)

Inherit from ServiceBase class - MSDN

A service is a long-running executable. It does not provide a user interface, and does not require any user to be logged onto the computer. Services run as System, but it is possible to choose to have them run under a different user account. The ServiceBase class is a base class for a service. It must be derived from when creating a new service.
Almost all services will override the OnStart and OnStop methods of ServiceBase.

ServiceController class and ServiceControllerPermission class

ServiceController class - MSDN
ServiceControllerPermission class - MSDN

ServiceInstaller and ServiceProcessInstaller class

ServiceInstaller - MSDN
ServiceProcessInstaller class - MSDN

ServiceChangeDescription structure and ServiceChangeReason enumeration

SessionChangeDescription structure - MSDN
SessionChangeReason enumeration - MSDN

Develop multithreaded applications

Exam objective: Develop multithreaded .NET Framework applications

(Refer System.Threading namespace)

Thread class - MSDN

ThreadPool class - MSDN

ThreadStart delegate, ParameterizedThreadStart delegate, and SynchronizationContext class

ThreadStart delegate - MSDN
The simplest way to create a thread is to instantiate the Thread class. The Thread constructor takes a delegate argument. The ThreadStart delegate points to a method containing your logic. For example:
Thread t1 = new Thread (new ThreadStart(LengthyLogic));
public void LengthyLogic ()
{
  // Logic code
}
ParameterizedThreadStart delegate - MSDN
When you start a thread, sometimes you need to pass in some data for processing. .NET 2.0 provides a new delegate, ParameterizedThreadStart, which takes a parameter of type object. The class has a new overload function Thread.Start. It allows you to specify the value to be passed into the thread. This approach is simple, but is not type-safe. Example:
Thread t1 = new Thread(new ParameterizedThreadStart(LengthyLogic));
// Use the overload of the Start method that has a parameter of type Object.
t1.Start(myData);
static void LengthyLogic(object data)
{
  // Logic code
}
SynchronizationContext class - MSDN
The Code Project Example for SynchronizationContext Class [1]

Timeout class, Timer class, TimerCallback delegate, WaitCallback delegate, WaitHandle class, and WaitOrTimerCallback delegate

Timeout class - MSDN
Timer class - MSDN
TimerCallback delegate - MSDN
WaitCallback delegate - MSDN
WaitHandle class - MSDN
WaitOrTimerCallback delegate - MSDN

ThreadExceptionEventArgs class and ThreadExceptionEventHanlder class

ThreadExceptionEventArgs class - MSDN
ThreadExceptionEventHandler class - MSDN

ThreadState enumeration and ThreadPriority enumeration

ThreadState enumeration - MSDN
ThreadPriority enumeration - MSDN

ReaderWriterLock class - MSDN

AutoResetEvent class and ManualResetEvent class

AutoResetEvent class - MSDN
ManualResetEvent class - MSDN

IAsyncResult interface and ICancelableAsyncResult interface

(Refer System namespace)
IAsyncResult interface - MSDN
ICancelableAsyncResult interface - MSDN

EventWaitHandle class, RegisterWaitHandle class, SendOrPostCallback delegate, and IOCompletionCallback delegate

EventWaitHandle class - MSDN
RegisterWaitHandle class - MSDN
This is a typo in the exam list of objectives and the training kit. The term RegisterWaitForSingleObject should be saerch instead (see KB)
SendOrPostCallback delegate - MSDN
IOCompletionCallback delegate - MSDN

Interlocked class, NativeOverlapped structure, and Overlapped class

Interlocked class - MSDN
NativeOverlapped structure - MSDN
Overlapped class - MSDN

ExecutionContext class, HostExecutionContext class, HostExecutionContext manager, and ContextCallback delegate

ExecutionContext class - MSDN
HostExecutionContext class - MSDN
HostExecutionContext manager - MSDN
In fact was is referred to here is the HostExecutionContextManager class
ContextCallback delegate - MSDN

LockCookie structure, Monitor class, Mutex class, and Semaphore class MSDN]

LockCookie structure - MSDN
Monitor class - MSDN
Mutex class - MSDN
Semaphore class - MSDN
Lock vs Monitor vs Mutex - MSDN

Using applications domains

Exam objective: Create a unit of isolation for common language runtime in a .NET Framework application by using application domains

(Refer System namespace)

Create an application domain

See MSDN

An application domain is a division of a process into multiple parts. Applications running in different application domains are as isolated as they would be in different processes. So they cannot access memory in another application domain. However, if native code is run, it can gain unlimited access to the whole process, which includes other application domains.

Application domains are easier to maintain and are faster because it is easier to communicate between application domains than between processes. An application domain can hold multiple assemblies.

To create an application domain, you must at least supply a name for the new application domain:

 AppDomain ad = AppDomain.CreateDomain("Name");

Use AppDomain.CurrentDomain to get the application domain the calling thread is using.

Load assemblies into an application domain

See MSDN

It is possible to execute an assembly by name using AppDomain.ExecuteAssemblyByName:

 AppDomain ad = AppDomain.CreateDomain("Name");
 ad.ExecuteAssemblyByName("aname, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a9b8c7d6");

Or use AppDomain.ExecuteAssembly to supply a path to the assemby:

 AppDomain ad = AppDomain.CreateDomain("Name");
 ad.ExecuteAssembly(@"c:\path\to\file.exe");
Unload an application domain

See MSDN

It is not possible to unload assemblies from the default application domain. However if an assembly is loaded in a different application domain, you can unload the whole application domain which includes all assemblies in that application domain.

To unload an application domain, use the static AppDomain.Unload function:

 AppDomain ad = AppDomain.CreateDomain("Name");
 AppDomain.Unload(ad);  
Configure an application domain

See MSDN

The most likely reason to modify the application domain configuration, is to restrict certain permissions to limit the damage if an attacker exploits vulnerabilities in an assembly.

An example is to run an assembly in the Internet Zone. The Internet Zone has limited permissions. To do this create a Zone Evidence and supply it as a parameter when creating the Application Domain:

 object [] myEvidenceTypes = {new Zone (SecurityZone.Internet)};
 Evidence myEvidence = new  Evidence(myEvidenceTypes, null);
 AppDomain ad = AppDomain.CreateDomain("Name", myEvidence); // Pass the Evidence when creating the App. Domain
 ad.ExecuteAssembly(@"c:\path\to\file.exe");
 

It is also possible to execute only one assembly in an Application Domain with different permissions;

 object [] myEvidenceTypes = {new Zone (SecurityZone.Internet)};
 Evidence myEvidence = new  Evidence(myEvidenceTypes, null);
 AppDomain ad = AppDomain.CreateDomain("Name");
 ad.ExecuteAssembly(@"c:\path\to\file.exe", myEvidence); // Pass the Evidence in the ExecuteAssembly function

Except Evidence, you can also use the AppDomainSetup class to set other properties.

 AppDomainSetup ads = new AppDomainSetup();
 ads.ApplicationBase = @"c:\Test";
 ads.DisallowCodeDownload = true;
 AppDomain ad = AppDomain.CreateDomain("Name", null, ads); // use null as second parameter for default Evidence
Retrieve setup information from an application domain

See MSDN

Use the SetupInformation property of an AppDomain to read the settings from that application domain;

 AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
 Console.WriteLine(ads.ConfigurationFile);
 Console.WriteLine(ads.ApplicationName);


Configuration, diagnostic, management, and installation

Exam objective: Embedding configuration, diagnostic, management, and installation features into a .NET Framework application

Topics

Configuration management

Configuration management is used here in a restricted sense. It refers to the adaptation of an application to a specific execution environment or user. This is usually done thru the use of configuration files that specify the run time parameters of the application. The typical example of such configuration information is the connection string used to locate and connect to the application database. The exam objectives are all related to the actual interaction of the application with its configuration files.

The management or the design of the configuration files themselves is a vast subject that is not touched by the exam objectives so we will not cover it in this study guide.

.NET framework installer

Event log

MSDN's definition is "Windows event logs allow your applications and components to record information about important events. You can use these records to audit access to your system, troubleshoot problems, and re-create usage patterns"

For a general discussion see MSDN

For specifics on the EventLog class and some cautions about its use see MSDN

Performance monitoring

Debugging and tracing

Management information and events

Windows Management Instrumentation - MSDN



Clipboard

To do:
Describe integration of WMI in .NET


Classes, Interfaces, and tools

Embed configuration management

Exam objective: Embed configuration management functionality into a .NET Framework application.

(Refer System.Configuration namespace)

Configuration class and ConfigurationManager class

Configuration class - MSDN
ConfigurationManager class - MSDN

ConfigurationSettings class, ConfigurationElement class, ConfigurationElementCollection class, and ConfigurationElementProperty class

ConfigurationSettings class - MSDN
ConfigurationElement class - MSDN
ConfigurationElementCollection class - MSDN
ConfigurationElementProperty class - MSDN

Implement IConfigurationSectionHandler interface - MSDN

ConfigurationSection class, ConfigurationSectionCollection class, ConfigurationSectionGroup class, and ConfigurationSectionGroupCollection class

ConfigurationSection class - MSDN
ConfigurationSectionCollection class - MSDN
ConfigurationSectionGroup class - MSDN
ConfigurationSectionGroupCollection - MSDN

Implement ISettingsProviderService interface - MSDN

Implement IApplicationSettingsProvider interface - MSDN

ConfigurationValidationBase class - MSDN

No direct result on MSDN - to be checked

Implement IConfigurationSystem interface - MSDN

Create custom installer and configure application

Exam objective: Create a custom Microsoft Windows Installer for .NET Framework components by using the System.Configuration.Install namespace, and configure the .NET Framework applications by using configuration files, environment variables, and the .NET Framework Configuration tool (Mscorcfg.msc).

For a "cookbook" on for the procedures discussed in this section see MSDN and the corresponding How-To section.

Installer class - MSDN

Configure which runtime version a .NET Framework application should use - MSDN

Configure where the runtime should search for an assembly - MSDN

Configure the location of an assembly and which version of the assembly to use - MSDN and MSDN

Direct the runtime to use the DEVPATH environment variable when searching for assemblies - MSDN

AssemblyInstaller class - MSDN

ComponentInstaller class - MSDN

Configure a .NET Framework application by using the .NET Framework Configuration tool (Mscorcfg.msc) - MSDN

ManagedInstaller class - MSDN

InstallContext class - MSDN

InstallerCollection class - MSDN

Implement IManagedInstaller interface - MSDN

InstallEventHandler delegate - MSDN

Configure concurrent garbage collection - MSDN

Register remote objects by using configuration files - MSDN

Manage an event log

Exam objective: Manage an event log by using the System.Diagnostics namespace

EventLog class - MSDN

EventSourceCreationData class - MSDN

Write to an event log

MSDN

Read from an event log

MSDN

Create a new event log

You create an EventLog by creating the first event source that writes to that log.

The two simplest way to do this are:

  • Use the EventLog.CreateEventSource method
  • Create an EventLog instance, specify a source and then write to the log. The actual creation takes place on execution of the first write.

Note that there is no "EventSource" class in the System.Diagnostics namespace even though an object representing the source is created in the registry.

C# EventLog creation Example

   using System;
   using System.Collections.Generic;
   using System.Text;
   using System.Diagnostics;
   namespace EventLogLab1
   {
       class Program
       {
           static void Main(string[] args)
           {
               try
               {
                   EventLog log1 = new EventLog("EvtLab2Log");
                   log1.Source = "EvtLab2Source";
                   // Actual creation happens next
                   log1.WriteEntry("Example message", EventLogEntryType.Information,
                       123, 1);
               }
               catch (Exception e)
               {
                   Console.WriteLine(e.Message);
               }
               Console.WriteLine("Press ENTER to finish");
               Console.ReadLine();
           }
       }
   }

The recommended way, which does not seem to be covered on the Training Kit (so probably not on the exam) is to use the EventLogInstaller class during the installation of the application. For reference purposes see MSDN

Manage processes and monitor performance

Exam objective: Manage system processes and monitor the performance of a .NET Framework application by using the diagnostics functionality of the .NET Framework 2.0.

(Refer System.Diagnostics namespace)

Get a list of all running processes.

Process class - MSDN
For example code for GetCurrentProcess(), GetProcessesByName(), GetProcesses(), and GetProcessById() see MSDN

Retrieve information about the current process - MSDN

Get a list of all modules loaded by a process

The Process.Modules property returns a strongly-typed collection of ProcessModule objects that represent the Process' currently loaded modules.
For the Process.Modules property see MSDN
For the ProcessModule class see MSDN

PerformanceCounter class, PerformanceCounterCategory, and CounterCreationData class

PerformanceCounter class - MSDN
PerformanceCounterCategory - MSDN
CounterCreationData class - MSDN

Start a process both by using and by not using command-line arguments

Starting a Process Overview
Processes are started using one of the overloaded Process.Start() methods. When passing sensitive data such as passwords to Process.Start(), use one of the two overloaded Start() methods that accept a SecureString as an argument type.
External links

StackTrace class - MSDN

StackFrame class - MSDN

Debug and Trace

Exam objective: Debug and trace a .NET Framework application by using the System.Diagnostics namespace.

Debug class and Debugger class

Debug class - MSDN
The four static writing methods of the Debug class - Write, WriteLine, WriteIf and WriteLineIf - let you write debug messages to inspect your program's flow and catch errors. Calls to these methods are ignored in the release version of your program (see 'The ConditionalAttribute attribute' below for details).
In Visual Studio, the default target for Debug's write methods is the Output window. You can use Debug's Listeners property to access the associated TraceListenerCollection. The following code shows how to use the Remove and Add methods of the collection to control where debug messages are sent to. If you add more than one listener of the same type, the associated target receives the text multiple times.
C# Code sample

Debug class example

   using System;
   using System.Diagnostics;
   using System.IO;
   using System.Reflection;
   class Program
   {
       static void Main(string[] args)
       {
           Debug.WriteLine("This is (by default) printed in the Output window.");
           //remove default listener
           Debug.Listeners.RemoveAt(0);
           //add a listener that can write to the Console window
           Debug.Listeners.Add(new ConsoleTraceListener());
           Debug.WriteLine("This is printed in the console window.");
           //add a default listener again
           Debug.Listeners.Add(new DefaultTraceListener());
           Debug.WriteLine("This is printed in both the Output and the Console window.");
           //remove all listeners
           Debug.Listeners.Clear();
           //add a listener that writes to a file
           Debug.Listeners.Add(new TextWriterTraceListener(File.Create("C:\\test.txt")));
           Debug.WriteLine("This is only printed to the newly created file.");
           //here we need to flush the output buffer
           Debug.Flush();
           //keep console window open in debug mode
           Console.ReadLine();
       }
   }
Debugger class - MSDN

Trace class - MSDN

CorrelationManager class - MSDN

TraceListener class - MSDN

TraceSource class - MSDN

TraceSwitch class - MSDN

XmlWriterTraceListener class - MSDN

DelimitedListTraceListener class - MSDN

EventlogTraceListener class - MSDN

Debugger attributes - MSDN

DebuggerBrowsableAttribute class - MSDN
DebuggerDisplayAttribute class - MSDN
DebuggerHiddenAttribute class - MSDN
DebuggerNonUserCodeAttribute class - MSDN
DebuggerStepperBoundaryAttribute class - MSDN
DebuggerStepThroughAttribute class - MSDN
DebuggerTypeProxyAttribute class - MSDN
DebuggerVisualizerAttribute class - MSDN

Embed management information

Exam objective: Embed management information and events into a .NET Framework application.

(Refer System.Management namespace - MSDN)

Retrieve a collection of Management objects by using the ManagementObjectSearcher class and its derived classes

The classes in the System.Management namespace let you use Windows Management Instrumentation (WMI) to manage computer systems. The most notable class in this namespace is ManagementObjectSearcher, that you can use to retrieve management objects based on a WMI query.
Information that can be retrieved this way ranges from computer case type (notebook, desktop...) over processor and hard disks details to information about running services and processes. Consult the WMI Reference on MSDN for an overview of all WMI classes and their properties.
In the example below a rough and dirty method is defined that prints all properties for all management information objects of a given WMI class. It is then used to print information about the current computer system.
C# Sample Code

WMI basic example

   class Program
   {
       static void Main(string[] args)
       {
           //Print all management info in the WMI class Win32_ComputerSystem
           PrintManagementInfo("Win32_ComputerSystem");
           //wait for user input to keep console window up in debug mode
           Console.ReadLine();
       }
       static void PrintManagementInfo(string WMIClassName)
       {
           ManagementObjectSearcher mos;
           //Get all managementobjects of the specified class
           mos = new ManagementObjectSearcher("SELECT * FROM " + WMIClassName);
           foreach (ManagementObject MOCollection in mos.Get())
           {
               foreach (PropertyData p in MOCollection.Properties)
               {
                   //Some properties are arrays,
                   //in which case the code below only prints
                   //the type of the array.
                   //Add a check with IsArray() and a loop
                   //to display the individual array values.
                   Console.WriteLine("{0}: {1}", p.Name, p.Value);
               }
           }
       }
   }
ManagementObjectSearcher class - MSDN
Enumerate all disk drivers, network adapters, and processes on a computer
The following code uses one overload of the ManagementObjectSearcher constructor to list all physical and logical disk drives, network adapters and running processes on a system.
C# Sample Code

ManagementObjectSearcher example

   class Program
   {
       static void Main(string[] args)
       {
           //
           Console.WriteLine("Physical disks: ");
           PrintManagementInfoProperty("Win32_DiskDrive", "Name");
           Console.WriteLine("*****************************");
           //
           Console.WriteLine("Logical disks: ");
           PrintManagementInfoProperty("Win32_LogicalDisk", "Name");
           Console.WriteLine("*****************************");
           //
           Console.WriteLine("Network adapters: ");
           PrintManagementInfoProperty("Win32_NetworkAdapter", "Name");
           Console.WriteLine("*****************************");
           //  
           Console.WriteLine("Processes: ");
           PrintManagementInfoProperty("Win32_Process", "Name");
           Console.WriteLine("*****************************");
           //  
           //wait for user input to keep console window up in debug mode
           Console.ReadLine();
       }
       static void PrintManagementInfoProperty(string WMIClassName, string WMIPropertyName)
       {
           ManagementObjectSearcher mos;
           //Get the specified property for all objects of the specified class
           mos = new ManagementObjectSearcher("SELECT " + WMIPropertyName + " FROM " + WMIClassName);
           foreach (ManagementObject mo in mos.Get())
           {
               PropertyData p = mo.Properties[WMIPropertyName]; 
               Console.WriteLine("{0}", p.Value);
           }
       }
   }
Retrieve information about all network connections
Example to be provided
Retrieve information about all services that are paused
The following code uses a ManagementObjectSearcher object to retrieve all running services and then displays their names.
C# Sample Code

Enumarating services example

   class Program
   {
       static void Main(string[] args)
       {
           Console.WriteLine("Running services: ");
           //form the query, providing a WMI class name and a condition
           SelectQuery query = new SelectQuery("Win32_Service", "State='Running'");
           //find matching management objects
           ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
           //
           foreach (ManagementObject mo in mos.Get())
           {
               Console.WriteLine(mo.Properties["Name"].Value);
           }
           //                        
           //wait for user input to keep console window up in debug mode
           Console.ReadLine();
       }
   }

ManagementQuery class - MSDN

EventQuery class - MSDN

ObjectQuery class - MSDN

Subscribe to management events by using the ManagementEventWatcher class - MSDN


Serialization and Input/Output

Exam objective: Implementing serialization and input/output functionality in a .NET Framework application

Topics

Serialization

Wikipedia's definition for serialization is : "in the context of data storage and transmission, serialization is the process of saving an object onto a storage medium (such as a file, or a memory buffer) or to transmit it across a network connection link in binary form".

The problem that is addressed here is that an object is created by a running process and is thus bound to the lifetime of that process instance. If for whatever reason, and there can be many, you want to "transport" the object in the context of another process instance you've got a problem, that you solve by "saving" the state of you object in the original process and "restoring" it in the destination process. This "saving" part is called serialization and the "restoring" part is called deserialization.

Serializable attribute

An object is serializable if its class name is prefixed with the [Serializable] attribute.

Object Serialization

One can use the BinaryFormatter class to serialize an object. To serialize, use the BinaryFormatter's Serialize() method which takes a stream and a serializable object as parameters. To deserialize, use the BinaryFormatter's Deserialize() method which takes a stream as a parameter and returns a object that can be cast back to the original object type. Remember to close streams after you use them by calling the stream's Close() method.

XML Serialization

One can use the XmlSerializer class to serialize an object. To serialize, use the XmlSerializer's Serialize() method which takes a stream and a serializable object as parameters. To deserialize, use the XmlSerializer's Deserialize() method which takes a stream as a parameter and returns a object that can be cast back to the original object type. Remember to close streams after you use them by calling the stream's Close() method.

For an overview of XML and SOAP serialization see MSDN

Custom Serialization

The ISerializable interface allows an object to control its own serialization and deserialization.

Readers

Writers

Formatters

A formatter is used to serialize objects into streams.

Streams

File IO

Managing Byte Streams

Compression

Isolated storage

For a general discussion on IsolatedStorage tasks see MSDN

Classes, Interfaces, and tools

Serialize and deserialize

Exam objective: Serialize or deserialize an object or an object graph by using runtime serialization techniques.

(Refer System.Runtime.Serialization namespace)

Serialization interfaces

IDeserializationCallback interface - MSDN

IFormatter interface and IFormatterConverter interface

IFormatter interface - MSDN
IFormatterConverter interface - MSDN

ISerializable interface - MSDN

Serialization attributes
For some serialization attributes exemple see MSDN

OnDeserializedAttribute class and OnDeserializingAttribute class

OnDeserializedAttribute class - MSDN
OnDeserializingAttribute class - MSDN

OnSerializedAttribute class and OnSerializingAttribute class

OnSerializedAttribute class - MSDN
OnSerializingAttribute class - MSDN

OptionalFieldAttribute class - MSDN

SerializationEntry structure and SerializationInfo class

SerializationEntry structure - MSDN

SerializationInfo class - MSDN

ObjectManager class

ObjectManager class - MSDN

Formatter class, FormatterConverter class, and FormatterServices class

Formatter class - MSDN

FormatterConverter class - MSDN

FormatterServices class - MSDN

StreamingContext structure

StreamingContext structure - MSDN

XML Serialization

Exam objective: Control the serialization of an object into XML format by using the System.Xml.Serialization namespace.

XmlSerializer class - MSDN

Exam objective: Serialize and deserialize objects into XML format by using the XmlSerializer class

Control serialization by using serialization attributes - MSDN

For a list of attributes for controlling serialization see MSDN

Implement XML Serialization interfaces to provide custom formatting for XML serialization - MSDN

Delegates and event handlers are provided by the System.Xml.Serialization namespace - MSDN

Custom serialization

Exam objective: Implement custom serialization formatting by using the Serialization Formatter classes.

SoapFormatter class - MSDN

(Refer System.Runtime.Serialization.Formatters.Soap namespace)

BinaryFormatter class - MSDN

(Refer System.Runtime.Serialization.Formatters.Binary namespace

File system classes

Exam objective: Access files and folders by using the File System classes.

(Refer System.IO namespace)

File class and FileInfo class

For common IO tasks see MSDN
File class - MSDN
FileInfo class - MSDN

Directory class and DirectoryInfo class

Directory class - MSDN
DirectoryInfo class - MSDN

DriveInfo class and DriveType enumeration

DriveInfo class - MSDN
DriveType enumeration - MSDN

FileSystemInfo class and FileSystemWatcher class

FileSystemInfo class
FileSystemWatcher class
The FileSystemWatcher class is designed to detected changes in the filesystem.
It can be parametrised with the Filter and Path Property.
  Example: 
  FileSystemWatcher w = new FileSystemWatcher();
  w.Filter = "*.txt";
  w.Path = @"C:\Windows";
The Filter property is only used to check the pattern of a file name. So do not use a directory path there.
You can add methods such as the WaitForChanged(..) to watch for changes in the specified area.

Path class - MSDN

The System.IO.Path class has many useful static methods for creating and parsing resource paths.

ErrorEventArgs class and ErrorEventHandler delegate

ErrorEventArgs class - MSDN
ErrorEventHandler delegate - MSDN

RenamedEventArgs class and RenamedEventHandler delegate

RenamedEventArgs class - MSDN
RenamedEventHandler delegate - MSDN

Byte streams

Exam objective: Manage byte streams by using Stream classes.

(Refer System.IO namespace)

FileStream class - MSDN

Stream class - MSDN

System.IO.Stream is the abstract base class that all other streams inherit from. It is not possible in instantiate a Stream class. Instead use one of the other classes that derive from Stream.
In terms of the 70-536 exam objectives, the most important classes that inherit from Stream are:
  • System.IO.FileStream
  • System.IO.MemoryStream
  • System.IO.Compression.DeflateStream
  • System.IO.Compression.GZipStream
  • System.Security.Cryptography.CryptoStream
  • System.IO.BufferedStream
For a complete list of classes that inherit from Stream see MSDN.
For a discussion on File and Stream IO see MSDN.

MemoryStream class - MSDN

BufferedStream class - MSDN

Reader and Writer classes

Exam objective: Manage the .NET Framework application data by using Reader and Writer classes.

(Refer System.IO namespace)

StringReader class and StringWriter class - MSDN and MSDN

StringReader and StringWriter inherit from TextReader/TextWriter.
  • StringReader is a TextReader for strings.
  • StringWriter is a TextWriter for strings.

TextReader class and TextWriter class

TextReader class - MSDN
TextReader and TextWriter are abstract base classes that StreamReader, StreamWriter, StringReader, and StringWriter derive from. StreamReader and StringReader derive from TextReader. StreamWriter and StringWriter derive from TextWriter.
TextWriter class - MSDN

StreamReader class and StreamWriter class - MSDN and MSDN

The StreamReader and StreamWriter classes provide basic functionality for reading and writing to character-based streams (ReadLine(), WriteLine(), ReadToEnd()).
StreamReader and StreamWriter inherit from the abstract classes TextReader and TextWriter:
  • StreamReader is a TextReader of streams.
  • StreamWriter is a TextWriter of streams.
The Peek and the Read method of a StreamReader:
  • The Peek-method gets the character at a certain position, but does not advance.
  • The Read-method gets the character at a certain position and advances.

BinaryReader class and BinaryWriter class

BinaryReader class - MSDN
BinaryWriter class - MSDN

Compression and isolated storage

Exam objective: Compress or decompress stream information in a .NET Framework application and improve the security of application data by using isolated storage.

(Refer System.IO.Compression namespace)

(Refer System.IO.IsolatedStorage namespace)

IsolatedStorageFile class - MSDN

IsolatedStorageFileStream class - MSDN

DeflateStream class - MSDN

GZipStream class - MSDN


Security

Exam objective: Improving the security of the .NET Framework applications by using the .NET Framework 2.0 security features

Topics

Code access security

Code access security, CAS, allows the control of various permissions granted to specific managed applications. MSDN

Permissions allow access to system resources. A permission set is a collection of permissions. A code group relates exactly one permission set to exactly one evidence type. Evidence is used to identify an assembly. Evidence types can include the application directory, cryptographic hash of the assembly, publisher's digital signature, site from which the assembly was downloaded, cryptographic strong name of the assembly, URL from which the assembly was downloaded, and the security zone in which the assembly is running. Security zones include the computer zone, local Intranet zone, Internet zone, trusted site, and untrusted sites. See the Internet options security tab in Internet Explorer to view various security zones. An assembly can be associated with multiple code groups. Permission sets can be associated with multiple code groups.

A security policy is a logical grouping of code groups and permission sets. An untrusted managed assembly must pass through four security policies: The Enterprise security policy, machine security policy, user security policy, and application domain security policy. Any one of these security policies can deny an untrusted managed assembly permissions.

Classes, interfaces, and tools

Implement code access security

Exam objective: Implement code access security to improve the security of a .NET Framework application.

(Refer System.Security namespace)

SecurityManager class - MSDN

CodeAccessPermission class - MSDN

Modify the Code Access security policy at the machine, user, and enterprise policy level by using the Code Access Security Policy tool (Caspol.exe) - MSDN

PermissionSet class, NamedPermissionSet class, and PermissionSetCollection class

PermissionSet class - MSDN
NamedPermissionSet class - MSDN
PermissionSetCollection class
There does not seem to be such a thing, to be investigated...

Standard Security interfaces

IEvidenceFactory interface - MSDN
IPermission interface - MSDN

Implement access control

Exam objective: Implement access control by using the System.Security.AccessControl classes.

DirectorySecurity class, FileSecurity class, FileSystemSecurity class, and RegistrySecurity class

DirectorySecurity class - MSDN
FileSecurity class - MSDN
FileSystemSecurity class - MSDN
RegistrySecurity class - MSDN

AccessRule class - MSDN

AuthorizationRule class and AuthorizationRuleCollection class

AuthorizationRule class - MSDN
AuthorizationRuleCollection class - MSDN

CommonAce class, CommonAcl class, CompoundAce class, GenericAce class, and GenericAcl class

CommonAce class - MSDN
CommonAcl class - MSDN
CompoundAce class - MSDN
GenericAce class - MSDN
GenericAcl class - MSDN

AuditRule class - MSDN

MutexSecurity class, ObjectSecurity class, and SemaphoreSecurity class

MutexSecurity class - MSDN
ObjectSecurity class - MSDN
SemaphoreSecurity class - MSDN

Implement custom authentication scheme

Exam objective: Implement a custom authentication scheme by using the System.Security.Authentication classes.

(Refer System.Security.Authentication namespace - MSDN)

For a reference on custom authentification schemes see MSDN

Encrypt, decrypt and hash data

Exam objective: Encrypt, decrypt, and hash data by using the System.Security.Cryptography classes.

(Refer System.Security.Cryptography namespace)

DES class and DESCryptoServiceProvider class

DES class - MSDN
DESCryptoServiceProvider class - MSDN

HashAlgorithm class - MSDN

DSA class and DSACryptoServiceProvider class

DSA class - MSDN
DSACryptoServiceProvider class - MSDN

SHA1 class and SHA1CryptoServiceProvider class

SHA1 class - MSDN
SHA1CryptoServiceProvider class - MSDN

TripleDES and TripleDESCryptoServiceProvider class

TripleDES - MSDN
TripleDESCryptoServiceProvider class - MSDN

MD5 class and MD5CryptoServiceProvider class

MD5 class - MSDN
MD5CryptoServiceProvider class - MSDN

RSA class and RSACryptoServiceProvider class

RSA class - MSDN
RSACryptoServiceProvider class - MSDN

RandomNumberGenerator class - MSDN

CryptoStream class - MSDN

CryptoConfig class - MSDN

RC2 class and RC2CryptoServiceProvider class

RC2 class - MSDN
RC2CryptoServiceProvider class - MSDN

AssymetricAlgorithm class MSDN

ProtectedData class and ProtectedMemory class

ProtectedData class - MSDN
ProtectedMemory class - MSDN

RijndaelManaged class and RijndaelManagedTransform class

RijndaelManaged class - MSDN
RijndaelManagedTransform class - MSDN

CspParameters class - MSDN

CryptoAPITransform class - MSDN

Hash-based Message Authentication Code (HMAC) - MSDN

HMACMD5 class - MSDN
HMACRIPEMD160 class - MSDN
HMACSHA1 class - MSDN
HMACSHA256 class - MSDN
HMACSHA384 class - MSDN
HMACSHA512 class - MSDN

Control permissions

Exam objective: Control permissions for resources by using the System.Security.Permission classes.

(Refer System.Security.Permission namespace)

SecurityPermission class - MSDN

PrincipalPermission class - MSDN

FileIOPermission class - MSDN

You can also set the FileIoPermisson attribute at assembly level or class level. Be then aware about the SecurityAction enumerations:
  • SecurityAction.RequestRefuse: specifies the operations that should not be granted.
  • SecurityAction.RequestMinumum: request for a minimum set of permissions. If not given, the app will not execute.

StrongNameIdentityPermission class - MSDN

UIPermission class - MSDN

UrlIdentityPermission class - MSDN

PublisherIdentityPermission class - MSDN

GacIdentityPermission class - MSDN

FileDialogPermission class - MSDN

DataProtectionPermission class - MSDN

EnvironmentPermission class - MSDN

IUnrestrictedPermission interface - MSDN

RegistryPermission class - MSDN

IsolatedStorageFilePermission class - MSDN

KeyContainerPermission class - MSDN

ReflectionPermission class - MSDN

StorePermission class - MSDN

SiteIdentityPermission class - MSDN

ZoneIdentityPermission class - MSDN

Control code privileges

Exam objective: Control code privileges by using System.Security.Policy classes.

(Refer System.Security.Policy namespace)

ApplicationSecurityInfo class and ApplicationSecurityManager class

ApplicationSecurityInfo class - MSDN
ApplicationSecurityManager class - MSDN

ApplicationTrust class and ApplicationTrustCollection class

ApplicationTrust class - MSDN
ApplicationTrustCollection class - MSDN

Evidence class and PermissionRequestEvidence class

Evidence class - MSDN
PermissionRequestEvidence class - MSDN

CodeGroup class, FileCodeGroup class, FirstMatchCodeGroup class, NetCodeGroup class, and UnionCodeGroup class

CodeGroup class - MSDN
FileCodeGroup class - MSDN
FirstMatchCodeGroup class - MSDN
NetCodeGroup class - MSDN
UnionCodeGroup class - MSDN

Condition classes

AllMembershipCondition class - MSDN
ApplicationDirectory class and ApplicationDirectoryMembershipCondition class
ApplicationDirectory class - MSDN
ApplicationDirectoryMembershipCondition class - MSDN
GacMembership class and GacMembershipCondition class
GacMembership class
No search results on MSDN!? a little investigation required here.
GacMembershipCondition class - MSDN
Hash class and HashMembershipCondition class
Hash class - MSDN
HashMembershipCondition class - MSDN
Publisher class and PublisherMembershipCondition class
Publisher class - MSDN
PublisherMembershipCondition class - MSDN
Site class and SiteMembershipCondition class
Site class - MSDN
SiteMembershipCondition class - MSDN
StrongName class and StrongNameMembershipCondition class
StrongName class - MSDN
StrongNameMembershipCondition class - MSDN
Url class and UrlMembershipConditon class
Url class - MSDN
UrlMembershipConditon class - MSDN
Zone class and ZoneMembershipCondition class
Zone class - MSDN
ZoneMembershipCondition class - MSDN

PolicyLevel class and PolicyStatement class

PolicyLevel class - MSDN
PolicyStatement class - MSDN

IApplicationTrustManager interface, IMembershipCondition interface, and IIdentityPermissionFactory interface

IApplicationTrustManager interface - MSDN
IMembershipCondition interface - MSDN
IIdentityPermissionFactory interface - MSDN

Access and modify identity information

Exam objective: Access and modify identity information by using the System.Security.Principal classes.

(Refer System.Security.Principal namespace)

GenericIdentity class and GenericPrincipal class

GenericIdentity class - MSDN
GenericPrincipal class - MSDN

WindowsIdentity class and WindowsPrincipal class

WindowsIdentity class - MSDN
WindowsPrincipal class - MSDN

NTAccount class and SecurityIdentifier class

NTAccount class - MSDN
SecurityIdentifier class - MSDN

IIdentity interface and IPrincipal interface

IIdentity interface - MSDN
IPrincipal interface - MSDN

WindowsImpersonationContext class - MSDN

IdentityReference class and IdentityReferenceCollection class

IdentityReference class - MSDN
IdentityReferenceCollection class - MSDN


Interoperability, Reflection, and Mailing

Exam objective: Implementing interoperability, reflection, and mailing functionality in a .NET Framework application


Topics

Interoperability

Reflection

The Wikipedia definition for reflection in computer science is: "The process by which a computer program can observe and modify its own structure and behavior. The programming paradigm driven by reflection is called reflective programming".

The concept is implemented extensively in .NET because a lot of information is maintained at the common intermediate language (CIL) level.

Among other things you can:

  • get information about running assembly or assembly constituents (modules, classes, methods, etc.), this is particularly useful for dynamically loaded assemblies that are not known at compile time.
  • put custom attributes in your code and retrieve those attributes at run time.
  • dynamically invoke methods.
  • "emit" and execute CIL code at run time.

Mailing

Classes, Interfaces, and tools

COM interoperability

Exam objective: Expose COM components to the .NET Framework and .NET Framework components to COM

(Refer System.Runtime.InteropServices namespace)

Exposing COM Components to the .NET Framework

First there is an article in the .NET developers guide that covers the first part of this section, see MSDN

Import a type library as an assembly - MSDN

Add references to type libraries
Same link as above, see second paragraph.
Type Library Importer (Tlbimp.exe) - MSDN
Generate interop assemblies from type libraries - MSDN
Imported Library Conversion - MSDN
Imported Module Conversion - MSDN
Imported Type Conversion - MSDN
Imported Member Conversion - MSDN
Imported Parameter Conversion - MSDN
TypeConverter class - MSDN

Create COM types in managed code - MSDN

Compile an interop project - MSDN

Deploy an interop application - MSDN

Exposing .NET Framework Components to COM

The rest of the objectives of that section directly refers to MSDN

Qualify the .NET Framework types for interoperation - MSDN

Apply Interop attributes, such as the ComVisibleAttribute class - MSDN

Package an assembly for COM - MSDN

Deploy an application for COM access - MSDN

Call DLL functions

Exam objective: Call unmanaged DLL functions in a .NET Framework application, and control the marshalling of data in a .NET Framework application.

(Refer System.Runtime.InteropServices namespace)

Platform Invoke - MSDN

Create a class to hold DLL functions - MSDN

Create prototypes in managed code - MSDN

DllImportAttribute class - MSND

Call a DLL function - MSDN

Look for "P/Invoke" on the internet.
A good reference is: http://www.pinvoke.net/
Some short hints:
  • For the DllAttribute "CharSet", Logically, CharSet.Auto is the most secure way as this will autodetect the Charset used. The CharSet can be ANSI(Win95/Win98/ME) or Unicode (Win2000/WinXP)
  • GetEntryPoint: There could be one tricky question as the EntryPoint states the method that should be called. In case the name of the method used differs from the method to be called, this flag is necessary.

Call a DLL function in special cases, such as passing structures and implementing callback functions

Same link as above
Passing structures - MSDN
Implementing callback functions - MSDN

Create a new Exception class and map it to an HRESULT - MSDN

Default marshaling behavior - MSDN

Marshal data with Platform Invoke - MSDN

Marshal data with COM Interop - MSDN

MarshalAsAttribute class and Marshal class

MarshalAsAttribute class - MSDN
Marshal class - MSDN

Implement Reflection

Exam objective: Implement reflection functionality in a .NET Framework application (refer System.Reflection namespace), and create metadata, Microsoft intermediate language (MSIL), and a PE file by using the System.Reflection.Emit namespace.

Building a custom attribute (annexes)

Assembly class -MSDN

Assembly attributes - MSDN

AssemblyAlgorithmIdAttribute class - MSDN
AssemblyCompanyAttribute class - MSDN
AssemblyConfigurationAttribute class - MSDN
AssemblyCopyrightAttribute class - MSDN
AssemblyCultureAttribute class - MSDN
AssemblyDefaultAliasAttribute class - MSDN
AssemblyDelaySignAttribute class - MSDN
AssemblyDescriptionAttribute class - MSDN
AssemblyFileVersionAttribute class - MSDN
AssemblyFlagsAttribute class - MSDN
AssemblyInformationalVersionAttribute class - MSDN
AssemblyKeyFileAttribute class - MSDN
AssemblyTitleAttribute class - MSDN
AssemblyTrademarkAttribute class - MSDN
AssemblyVersionAttribute class - MSDN

Info classes

ConstructorInfo class - MSDN
MethodInfo class - MSDN
MemberInfo class - MSDN
PropertyInfo class - MSDN
FieldInfo class - MSDN
EventInfo class - MSDN
LocalVariableInfo class - MSDN

Binder class and BindingFlags - MSDN

MethodBase class and MethodBody class

MethodBase class - MSDN
MethodBody class - MSDN

Builder classes

AssemblyBuilder class - MSDN
ConstructorBuilder class - MSDN
EnumBuilder class - MSDN
EventBuilder class - MSDN
FieldBuilder class - MSDN
LocalBuilder class - MSDN
MethodBuilder class - MSDN
ModuleBuilder class - MSDN
ParameterBuilder class - MSDN
PropertyBuilder class - MSDN
TypeBuilder class - MSDN

Send Electronic mail

Exam objective: Send electronic mail to a Simple Mail Transfer Protocol (SMTP) server for delivery from a .NET Framework application.

(Refer System.Net.Mail namespace)

MailMessage class - MSDN

MailAddress class and MailAddressCollection class

MailAddress class - MSDN
MailAddressCollection class - MSDN

SmtpClient class, SmtpPermission class, and SmtpPermissionAttribute class

SmtpClient class - MSDN
SmtpPermission class - MSDN
SmtpPermissionAttribute class - MSDN

Attachment class, AttachmentBase class, and AttachmentCollection class

Attachment class - MSDN
AttachmentBase class - MSDN
AttachmentCollection class - MSDN

SmtpException class, SmtpFailedReceipientException class, and SmtpFailedReceipientsException class

SmtpException class - MSDN
SmtpFailedReceipientException class - MSDN
Please note that there is a typo in the exam objective page here, they use SmtpFailedReceipientException instead of SmtpFailedRecipientException.
SmtpFailedRecipientsException class - MSDN
Same typo then above

SendCompleteEventHandler delegate - MSDN

LinkedResource class and LinkedResourceCollection class

LinkedResource class - MSDN
LinkedResourceCollection class - MSDN

AlternateView class and AlternateViewCollection class

AlternateView class - MSDN
AlternateViewCollection class - MSDN



Globalization, Drawing, and Text manipulation

Exam objective: Implementing globalization, drawing, and text manipulation functionality in a .NET Framework application

Topics

Globalization

Drawing

Text manipulation

Text manipulation, in the context of the exam objectives, covers 3 main subjects: string building, regular expressions and text encoding. We look at each in the following paragraphs.

String and StringBuilder classes

Text manipulation starts with the representation of a string which is done via the String class. No specific exam objective mentions the String class but we added a section for it because you must understand some of its specific characteristics.

Next comes the StringBuilder class that serves for efficient construction.

Regular expressions

The Regex, Match and Group classes together implement the regular expressions support in the .NET framework.

Regular expressions are a world by themselves and have been around for quite some time.

There is a wikibook on regular expressions which, among other things, point to this Tutorial.

Regular expressions support in .NET basically allows for:

  • testing the match of a string to a regex pattern (Regex.IsMatch method)
  • extracting the substrings that "match" part of a pattern (Regex.Match method with Match and Group classes).
Text encoding

Classes, Interfaces, and tools

Format data based on culture information.

(Refer System.Globalization namespace)

Access culture and region information

Exam objective: Access culture and region information in a .NET Framework application

CultureInfo class - MSDN

CultureTypes enumeration - MSDN

RegionInfo class - MSDN

Format date and time values based on the culture.

DateTimeFormatInfo class - MSDN

Format number values based on the culture.

NumberFormatInfo class - MSDN

NumberStyles enumeration - MSDN

Perform culture-sensitive string comparison.

CompareInfo class - MSDN

CompareOptions enumeration - MSDN

Custom culture

Exam objective: Build a custom culture class based on existing culture and region classes

CultureAndRegionInfoBuilder class - MSDN

CultureAndRegionModifier enumeration - MSDN

System.Drawing namespace

Exam objective: Enhance the user interface of a .NET Framework application by using the System.Drawing namespace.

Brushes, Pens, Colors and Fonts

Exam objective: Enhance the user interface of a .NET Framework application by using brushes, pens, colors, and fonts

Brush class - MSDN

Brushes class - MSDN

SystemBrushes class - MSDN

TextureBrush class - MSDN

Pen class - MSDN

Pens class - MSDN

SystemPens class - MSDN

SolidBrush class - MSDN

Color structure - MSDN

ColorConverter class - MSDN

ColorTranslator class - MSDN

SystemColors class - MSDN

StringFormat class - MSDN

Font class - MSDN

FontConverter class - MSDN

FontFamily class - MSDN

SystemFonts class - MSDN

Graphics, Images, Bitmaps and Icons

Exam objective: Enhance the user interface of a .NET Framework application by using graphics, images, bitmaps, and icons

Graphics class - MSDN

BufferedGraphics class - MSDN

BufferedGraphicsManager class - MSDN

Image class - MSDN

ImageConverter class - MSDN

ImageAnimator class - MSDN

Bitmap class - MSDN

Icon class - MSDN

IconConverter class - MSDN

SystemIcons class - MSDN

Shapes and Sizes

Exam objective: Enhance the user interface of a .NET Framework application by using shapes and sizes

Point Structure - MSDN

PointConverter class - MSDN

Rectangle Structure - MSDN

RectangleConverter class - MSDN

Size Structure - MSDN

SizeConverter class - MSDN

Region class - MSDN

Text handling and regular expressions

Exam objective: Enhance the text handling capabilities of a .NET Framework application, and search, modify, and control text in a .NET Framework application by using regular expressions

(Refer System.Text namespace)

(Refer System.RegularExpressions namespace)

String class

The String class is not a specific exam objective but was added to have a place to discuss some of its characteristics.

String class - MSDN

StringBuilder class

The StringBuilder class is used for very fast string concatenation. If you use conventional string concatenation then it will run very slow because a string is held in an array. Each concatenation causes the array to increase its size and the memory has to be copied to a new location internally. This is very slow.

For fast string concatenations use StringBuilder instead. It is about 1000 times faster (depending on the string you concatenate).

StringBuilder class - MSDN


Refer to the example to measure the performance differences.

C# example

StringBuilder example

using System;
using System.Collections;
public class Demo
{
    public static void Main()
    {
        const int len = 30;
        const int loops = 5000;
        //        
        DateTime timeStart, timeStop;
        //         
        // Measure time for normal string concatenation
        timeStart = DateTime.Now;
        string str = "";
        for (int i = 0; i < loops; i++)
        {
            str += new String('x', len);
        }
        timeStop = DateTime.Now;
        int millis = timeStop.Subtract(timeStart).Milliseconds;
        Console.WriteLine("Duration for " + loops + " loops: " + millis + " ms");
        //         
        // Measure time for StringBuilder string concatenation
        StringBuilder sb = new StringBuilder();
        timeStart = DateTime.Now;
        for (int i = 0; i < loops; i++)
        {
            sb.Append(new String('x', len));
        }
        str = sb.ToString();
        timeStop = DateTime.Now;
        millis = timeStop.Subtract(timeStart).Milliseconds;
        Console.WriteLine("Duration for " + loops + " loops: " + millis + " ms");
        //         
        Console.ReadLine();
    }
}
Regex class

Regex class - MSDN

Match class and MatchCollection class

Match class - MSDN

MatchCollection class - MSDN

Group class and GroupCollection class

Group class - MSDN

GroupCollection class - MSDN

Encode text by using Encoding classes

Encoding class - MSDN

EncodingInfo class - MSDN

ASCIIEncoding class - MSDN

UnicodeEncoding class - MSDN

UTF8Encoding class - MSDN

Encoding Fallback classes - MSDN

Decode text by using Decoding classes.

Decoder class - MSDN

Decoder Fallback classes - MSDN

Capture class and CaptureCollection class

Capture class - MSDN

CaptureCollection class - MSDN

See also

References

70-536 Training kit

.NET Framework Application Development Foundation Self-Paced Training Kit, Second Edition Tony Northrup Microsoft Press

We reference that book as the "training kit" since it is recommended by Microsoft as a training aid for the 70-536 exam (for example see MCPD).

If you use the training kit you might want to look here for a list of known corrections. Other potential corrections are listed in this wikibook.

C Sharp 2005

Visual C#: The language - 2005 Edition Donis Marchall Microsoft Press

Also recommended as a training aid for the 70-536 exam (for example see MCPD)

ECMA 335

If you want to go deeper into the definition of the common language infrastructure you can download the official specification

This is not required for the exam but we will use the specification a couple of times to clarify ambiguities in the MSDN documentation or other reference manuals.


Annexes

The annexes are a series of articles on specific subjects that are referenced by the main text but were not integrated in it.


Annexes: Generic types

Introduction

In order to understand Generics, we should first look why we would want to use them. This is best explained with a simple example. Let's say we want to create a collection of clients, this is something that we do often. We take a simple Client class that has a name and an account number. Often an ArrayList will be used to store multiple clients in memory like this:

  /// <summary>
  /// Representation of a client
  /// </summary>
  public class Client
  {
      private string _name;
      private string _accountNumber;
       
      /// <summary>
      /// Gets or sets the account number.
      /// </summary>
      /// <value>The account number.</value>
      public string AccountNumber
      {
          get { return _accountNumber; }
          set { _accountNumber = value; }
      }
       
      /// <summary>
      /// Gets or sets the name.
      /// </summary>
      /// <value>The name.</value>
      public string Name
      {
          get { return _name; }
          set { _name = value; }
      }
       
      /// <summary>
      /// Initializes a new instance of the <see cref="T:Client"/> class.
      /// </summary>
      /// <param name="name">The name.</param>
      /// <param name="accountNumber">The account number.</param>
      public Client(string name, string accountNumber)
      {
          _name = name;
          _accountNumber = accountNumber;
      }
       
      /// <summary>
      /// The Main entry point of the console application
      /// </summary>
      /// <param name="args">The command line arguments</param>
      static void Main(string[] args)
      {
          ArrayList clients = new ArrayList();
          clients.Add(new Client("Marco", "332-3355"));
          clients.Add(new Client("Martinus", "453-5662"));
          foreach (Client client in clients)
          {
              Console.WriteLine("The account {0} belongs to {1}", client.AccountNumber, client.Name);
          }
          Console.ReadLine();
      }
  }

This probably looks familiar for most of the readers, but by using an ArrayList we are not type safe, which is in my opinion is bad. Also we need to cast (and uncast) the object when we want to do something cool with it. With value types there is an other issue, we constantly Box and unbox the objects in the list.

A better way store the clients would be to use typed collections, this will solve the problem with type safety and we don’t have to cast the retrieved object every time we use it. A good way to do this is by inheriting an object form the CollectionBase class and looks like this:

  /// <summary>
  /// Representation of a client
  /// </summary>
  public class Client
  {
      private string _name;
      private string _accountNumber;
       
      /// <summary>
      /// Gets or sets the account number.
      /// </summary>
      /// <value>The account number.</value>
      public string AccountNumber
      {
          get { return _accountNumber; }
          set { _accountNumber = value; }
      }
       
      /// <summary>
      /// Gets or sets the name.
      /// </summary>
      /// <value>The name.</value>
      public string Name
      {
          get { return _name; }
          set { _name = value; }
      }
       
      /// <summary>
      /// Initializes a new instance of the <see cref="T:Client"/> class.
      /// </summary>
      /// <param name="name">The name.</param>
      /// <param name="accountNumber">The account number.</param>
      public Client(string name, string accountNumber)
      {
          _name = name;
          _accountNumber = accountNumber;
      }
       
      /// <summary>
      /// The Main entry point of the console application
      /// </summary>
      /// <param name="args">The command line arguments</param>
      static void Main(string[] args)
      {
          ClientList clients = new ClientList();
          clients.Add(new Client("Marco", "332-3355"));
          clients.Add(new Client("Martinus", "453-5662"));
          foreach (Client client in clients)
          {
              Console.WriteLine("The account {0} belongs to {1}", client.AccountNumber, client.Name);
          }
          Console.ReadLine();
      }
  }
           
  /// <summary>
  /// A list of clients
  /// </summary>
  public class ClientList : CollectionBase
  {
      /// <summary>
      /// Adds the specified client to the list.
      /// </summary>
      /// <param name="client">The client.</param>
      /// <returns></returns>
      public int Add(Client client)
      {
          return List.Add(client);
      }
       
      /// <summary>
      /// Gets or sets the <see cref="T:Client"/> at the specified index.
      /// </summary>
      /// <value></value>
      public Client this[int index]
      {
          get
          {
              return (Client)List[index];
          }
          set
          {
              List[index] = value;
          }
      }
  }


This looks a lot better than when we where using the ArrayList in the first example and is in general a good way to go. But what if your application grows, and we get more types that we want to store in collections like an Account, or a bank. With the 1.1 framework we had to create a new collection class for every type of object that we used, or fall back to the ugly ArrayList method. However with the new 2.0 framework MS has added Generics. This makes it possible to create classes and methods that use type parameters. This allows developers to create classes and methods that defer the specifications of certain types until the class is defined and instantiated in the code. By using the generic type parameters developers can write classes that others can use without incurring the risks involved with un-typed classes like ArrayList and reduces the work developers have to do compared to creating typed collections. So lets look at how the code looks when we are using the Generic List<T> class from the framework.

  /// <summary>
  /// Representation of a client
  /// </summary>
  public class Client
  {
      private string _name;
      private string _accountNumber;
       
      /// <summary>
      /// Gets or sets the account number.
      /// </summary>
      /// <value>The account number.</value>
      public string AccountNumber
      {
          get { return _accountNumber; }
          set { _accountNumber = value; }
      }
       
      /// <summary>
      /// Gets or sets the name.
      /// </summary>
      /// <value>The name.</value>
      public string Name
      {
          get { return _name; }
          set { _name = value; }
      }
       
      /// <summary>
      /// Initializes a new instance of the <see cref="T:Client"/> class.
      /// </summary>
      /// <param name="name">The name.</param>
      /// <param name="accountNumber">The account number.</param>
      public Client(string name, string accountNumber)
      {
          _name = name;
          _accountNumber = accountNumber;
      }
       
      /// <summary>
      /// The Main entry point of the console application
      /// </summary>
      /// <param name="args">The command line arguments</param>
      static void Main(string[] args)
      {
          List<Client> clients = new List<Client>();
          clients.Add(new Client("Marco", "332-3355"));
          clients.Add(new Client("Martinus", "453-5662"));
          foreach (Client client in clients)
          {
              Console.WriteLine("The account {0} belongs to {1}", client.AccountNumber, client.Name);
          }
          Console.ReadLine();
      }
  }

Thanks to Generics we have created a type-safe collection as easy as we would normally instantiate an ArrayList without writing our own typed collection. Now that we have had a brief look at how we can use Generics to reduce the amount of code we need to write, while still using typed collections let's see how we could create our custom Generic Class. To demonstrate this I have created an example Class which inherits from the DictionaryBase class. This implementation of the dictionary class will accept a GUID as the key and has a Type parameter as the value type. If you are a bit like me you will use GUIDS to identify your records in a database so using this as the key in a Typed collection was something I liked to do a lot. So now I’ve got a cool dictionary that I can use with all my objects I created when retrieving data from my database, and I will give you the code:

  /// <summary>
  /// Representation of a client
  /// </summary>
  public class Client
  {
      private string _name;
      private string _accountNumber;
       
      /// <summary>
      /// Gets or sets the account number.
      /// </summary>
      /// <value>The account number.</value>
      public string AccountNumber
      {
          get { return _accountNumber; }
          set { _accountNumber = value; }
      }
       
      /// <summary>
      /// Gets or sets the name.
      /// </summary>
      /// <value>The name.</value>
      public string Name
      {
          get { return _name; }
          set { _name = value; }
      }
       
      /// <summary>
      /// Initializes a new instance of the <see cref="T:Client"/> class.
      /// </summary>
      /// <param name="name">The name.</param>
      /// <param name="accountNumber">The account number.</param>
      public Client(string name, string accountNumber)
      {
          _name = name;
          _accountNumber = accountNumber;
      }
       
      /// <summary>
      /// The Main entry point of the console application
      /// </summary>
      /// <param name="args">The command line arguments</param>
      static void Main(string[] args)
      {
          GuidDictionary<Client> clients = new GuidDictionary<Client>();
          Guid clientID1 = Guid.NewGuid();
          Guid clientID2 = Guid.NewGuid();
          clients.Add(clientID1, new Client("Marco", "332-3355"));
          clients.Add(clientID2, new Client("Martinus", "453-5662"));
          Console.WriteLine("The account {0} belongs to {1}", clients[clientID1].AccountNumber, clients[clientID1].Name);
          Console.WriteLine("The account {0} belongs to {1}", clients[clientID2].AccountNumber, clients[clientID2].Name);
          Console.ReadLine();
      }
  }
       
  public class GuidDictionary<T> : DictionaryBase
  {
      public void Add(Guid id, T item)
      {
          Dictionary.Add(id, item);
      }
       
      public T this[Guid id]
      {
          get
          {
              return (T)Dictionary[id];
          }
          set
          {
              Dictionary[id] = value;
          }
      }
  }

Well it's probably not as wonderful as you expected, a lot of methods the standard dictionary has aren’t even implemented, but hey I have to leave some fun things to do for you the reader.

So what exactly did we do in the above code? We have created a Dictionary that is indexed by a Guid and uses a type parameter to limit our add method and our indexer. Now when we create a new instance of the class and specify the type parameter we have a type-safe dictionary which can be used to store and retrieve the type of objects by the given Guid.

The T in the declaration is only a name for the thing, we could as easily use the following: VeryLongNameForTheTypeParameter instead of T. Ok so we have seen how to use the type parameter to create a generic class. But before we move on to the next part lets look at the System.Collections.Generic.Dictionary<>. This class must be instantiated by providing 2 type parameters named TKey and TValue. This shows us that we can use more than one type parameter in our definition, and also shows that it was a waste of time to build my own dictionary class I could as easily used the generic dictionary like this: Dictionary<Guid, Client> and be over with it.


Annexes: Building custom attributes

Original text for this page authored by William "Scott" Baker

Attributes Summary

Attributes are a way to "tag" elements of your code's metadata with descriptive information that can be accessed at runtime using reflection. Attributes must derive from System.Attribute, either directly or indirectly. A multitude of attributes exist in the .NET framework; you can also define your own. There are three aspects to using attributes in your code:

  1. Defining a custom attribute class, which involves:
    1. Assigning the AttributeUsageAttribute attribute to your class.
    2. Writing the code to define your custom attribute class.
    3. Creating the parameters for your class.
  2. Assigning an attribute to a code member.
  3. Retrieving attribute information at runtime.

Creating a Custom Attribute Class

As previously mentioned, there are several predefined attributes in the .NET Framework; you may have already used them in your code. The XML parser in particular relies heavily on attributes when (de)serializing objects. You can also define your own custom attributes, as we will show here. Defining a custom attribute involves three steps:

  1. Assigning the AttributeUsageAttribute attribute to your class.
  2. Writing the code to define your custom attribute class.
  3. Creating the parameters for your class.

Assigning the "AttributeUsageAttribute" To Your Class

The "scope" and other characteristics of your attribute should be specified by the use of the AttributeUsageAttribute attribute.
Note: In Visual Basic, use of the AttributeUsageAttribute attribute is required on all custom attributes. Applying the AttributeUsageAttribute attribute to a class:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
public Class QualityCheckAttribute : System.Attribute 
{
  // ...
}

Notice the use of "AttributeUsage" vs. "AttributeUsageAttribute". By convention, all attributes are named with the "Attribute" suffix - but the suffix can be omitted when used in code. This holds true for user defined attributes as well; the QualityCheckAttribute attribute could be referenced as either:

[QualityCheck] // or... 
[QualityCheckAttribute]

The AttributeUsageAttribute has three members: ValidOn, AllowMultiple and Inherited.

  • The ValidOn member accepts AttributeTargets enum values, and restricts your attribute to the code types you specify. The default value is AttributeTargets.All. You can confine your attribute to classes, enums, return values or any of the list below:
All (any element)   Delegate    GenericParameter    Parameter
Assembly            Enum        Interface           Property
Class               Event       Method              ReturnValue
Constructor         Field       Module*             Struct

*Module refers to a portable executable (.exe or .dll), and not a Visual Basic standard module.

You can also combine target types as a bitwise OR operation to specify multiple acceptable values:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
  • AllowMultiple is a boolean value that determines whether or not an attribute can be applied more than once to a given member. The default value is false. The example below illustrates multiple instances of the same attribute on an element of code:
[QualityCheck("Scott Baker", "02/28/06", IsApproved = true,
   Comment = "This code follows all established guidelines.  Release approved.")]
[QualityCheck("Matt Kauffman", "01/15/06", IsApproved = false,
   Comment = "Code quality much improved. Minor revision required.")]
[QualityCheck("Joe Schmoe", 01/01/06", IsApproved = false,
   Comment = "This code is a mess and needs a complete rewrite")]
public class MyClass
{
// ... 
}
  • The Inherited member determines whether attributes set on a class will be inherited by classes further down the inheritance tree. The default value is true:
[AttributeUsage(AttributeTargets.Class)]
public class AttrOneAttribute : Attribute
{
  // ... 
}

// This attribute will not be inherited 
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class AttrTwoAttribute : Attribute
{
  // ... 
}

[AttrOne]
[AttrTwo]
public class ClassOne 
{
  // ... 
}

// This class inherits AttrOne from ClassOne, 
// but not AttrTwo 
public class ClassTwo : ClassOne
{
  // ... 
}

Defining A Custom Attribute Class

  • Attributes are classes that inherit from System.Attribute, either directly or indirectly:
public Class QualityCheckAttribute : System.Attribute // direct 
{
  // ...
}

public Class FinalCheck : QualityCheckAttribute  // indirect 
{
// ...
}
  • Attribute classes have the AttributeUsageAttribute attribute:
[AttributeUsage(AllowMultiple = true, Inherited = false)]
public Class QualityCheckAttribute : System.Attribute
{
  // ...
}

As previously mentioned, the use of AttributeUsageAttribute is required in VB. In C#, it is automatically applied with the default values if not declared.

Creating Parameters For An Attribute

Attributes accept two types of parameters: positional and named. Positional parameters are defined by public constructors in your class, must be in the order defined and are required; named parameters are defined by public properties, can be in any order and are optional.
Positional Parameters
Positional parameters for an attribute are defined by the constructors in the class. As with any class, constructors can be overloaded and a default constructor that takes no parameters can be defined. As with any other class, the signature of the positional parameters must match the signature of a constructor in the attribute class:
public class QualityCheckAttribute : Attribute
{
  public QualityCheckAttribute(string Name, string Date)
  // ... 
}
Named Parameters
Named parameters for an attribute are defined by public properties defined in the class. Named parameters are optional and are declared after any positional parameters. The IsApproved property demonstrates a named parameter:
public class QualityCheckAttribute : Attribute
{
  private string _name;
  private string _date;
  private bool isApproved;
  public bool IsApproved
  {
    get {return isApproved;}
    set {isApproved = value;}
  }
  public QualityCheckAttribute(string Name, string Date)
  {
    // ...
  }
}

Keep in mind that a variable in your code can be both a positional parameter and a named parameter. If we were to add public properties for the _name and _date fields we could use them either as named parameters or positional parameters. Of course, this is not a recommended practice: required parameters should be positional and optional parameters should be named.

Assigning An Attribute To A Code Member

You have already seen examples of assigning an attribute to a code member. However, there are some points that must be clarified.

  • Disambiguation is the clarification of the use of an attribute on a code member.
  • Syntax - there is more than one way to apply multiple attributes.

Disambiguation

The code below isn't clear as to whether SomeAttribute applies to the method MyMethod or to its return value:
public class MyAttribute : Attribute
{
  [SomeAttribute("Hello")]
  public string MyMethod(aString)
  {
    return aString;
  }
}

Disambiguation resolves these issues. By specifying the code type the attribute is applied to, we are able to resolve the confusion. The code below shows that the attribute applies to the return value:

public class MyAttribute : Attribute
{
  [return : SomeAttribute]
  public string MyMethod(aString)
  {
    return aString;
  }
}

The table below lists all declarations where attributes are allowed; for each declaration, the possible targets for attributes on the declaration are listed in the second column. Targets in bold are the defaults.

Declaration               Possible targets
assembly                  assembly
module                    module
class                     type
struct                    type
interface                 type
enum                      type
delegate                  type, return
method                    method, return
parameter                 param
field                     field
property — indexer        property
property — get accessor   method, return
property — set accessor   method, param, return
event — field             event, field, method
event — property          event, property
event — add               method, param
event — remove            method, param

*Reference: Disambiguating Attribute Targets (C# Programming Guide)

One would think that the AttributeUsageAttribute's AttributeTargets in an attribute's definition would help to prevent this confusion: one would be wrong. The compiler does not use the AttributeUsageAttribute information when resolving conflicts. Even if you define an attribute to apply only to a specific type, for instance AttributeTargets.Return, you must still clarify that it applies to the return type when applying the attribute or the compiler will use the default target method type, and throw an error.

Syntax: Applying Multiple Attributes

When applying more than one attribute to a member, there are two ways to do so:
[AttrOne(...), AttrTwo(...)]  
  // or...
[AttrOne(...)]
[AttrTwo(...)]

The two are equivalent. Keep in mind that if you are going to specify more than one attribute in a single brace, they must apply to the same target type. If not, you must give each type a separate declaration:

[return : AttrOne(...), method : AttrTwo(...)]  // <-- invalid!
  // instead, you must...
[return : AttrOne(...)]
[method : AttrTwo(...)]

Retrieving Attribute Information At Runtime

Being able to declare and apply attributes is not very helpful unless we can retrieve that data and do something with it. Fortunately, its a straightforward process. There are three basic scenarios that will be addressed:

  1. Retrieve a single attribute from a member.
  2. Retrieve multiple attributes from a member.
  3. Retrieve attributes of a single type from multiple members.

Retrieving A Single Attribute From A Member

To access attribute information:

  1. Declare an instance of the attribute type.
  2. Use the Attribute.GetCustomAttribute(type, typeof) method to read the attribute into the instance.
  3. Use the properties of the instance to read the values.

The example code below declares a class ExampleClass with a QualityCheck attribute. The GetSingleAttribute method accepts a target member type and the type of attribute you're looking for. The Attribute.GetCustomAttribute method retrieves the attribute information into the attr object, from which we can read the all-important IsApproved property:

[QualityCheck("Scott Baker", "02/04/2006", IsApproved = false)]
public class ExampleClass
{

  public static void Main()
  {
    GetSingleAttribute(typeof(ExampleClass), typeof(QualityCheck))
  }
 
  public static void GetSingleAttribute(Type targetType, Type attrType)
  {
    typeof(attrType) attr = (attrType)Attribute.GetCustomAttribute(targetType, typeof(attrType));
  
    if (attr == null)
    { //... }
    else
    {
      Console.Writeline(attr.IsApproved);
    }
  }

An important factor to keep in mind is that the GetCustomAttribute method is designed to read one and only one attribute. GetCustomAttribute actually checks to see if more than one attribute matches - if there is no match it returns null, but if there is more than one match it will throw an AmbiguousMatchException. When checking for attributes the only time it is safe to use GetCustomAttribute is when the attribute's definition states [AttributeUsage(AllowMultiple=false)].

Retrieving Multiple Attributes From A Member

Reading multiple instances of an attribute on a member isn't much different than reading one; to read multiple attributes use the plural GetCustomAttributes, which returns an array of attributes. You can then iterate through the resultant array and read the values:

QualityCheck[] attrArray = (QualityCheck[])Attribute.GetCustomAttributes(t, typeof(QualityCheck));

foreach (QualityCheck attr in attrArray)
{
  Console.Writeline(attr.IsApproved);
}

Retrieving A Single Attribute Type From Multiple Members

What if you want to do something a little more complex, like checking each method in a class for a QualityCheck attribute? Thanks to the System.Reflection namespace, we don't have to even break a sweat. Simply read all the members (methods, in this instance) into a MemberInfo array and iterate through them:

using System.Reflection

public class ExampleClass
{
  public static void Main()
  {
    RetrieveAttributes(typeof(ExampleClass));
  }

  public void RetrieveAttributes(Type t)
  {
    MemberInfo[] methodList = t.GetMethods();
    foreach (MemberInfo m in methodList)
    {
      QualityCheck[] attrArray = (QualityCheck[])Attribute.GetCustomAttributes(m, typeof(QualityCheck));
      foreach (QualityCheck attr in attrArray)
      {
        Console.Writeline(attr.IsApproved);
      }
    }
  }
}