Tuesday, 20 November 2012

Generics

Generics

To understand and appreciate the concept of generics, consider the need to create a class that will manage a collection of objects. The objects may be of any type and are specified at compile time by a parameter passed to the class. Moreover, the collection class must be type-safe—meaning that it will accept only objects of the specified type.
In the 1.x versions of .NET, there is no way to create such a class. Your best option is to create a class that contains an array (or other container type) that treats everything as an object. As shown here, casting, or an as operator, is then required to access the actual object type. It is also necessary to include code that verifies the stored object is the correct type.
Object[] myStack = new object[50];

myStack[0] = new Circle(5.0);    // place Circle object in array

myStack[1] = "Circle";           // place string in array

Circle c1 = myStack[0] as Circle;

if( c1!=null) {                  // circle object obtained

Circle c2 = (Circle) myStack[1]; // invalid case exception

Generics, introduced with .NET 2.0, offer an elegant solution that eliminates the casting, explicit type checking, and boxing that occurs for value type objects. The primary challenge of working with generics is getting used to the syntax, which can be used with a class, interface, or structure.
The best way to approach the syntax is to think of it as a way to pass the data type you'll be working with as a parameter to the generic class. Here is the declaration for a generic class:
public class myCollection<T>

{

   T[] myStack = new T[50];

}

The type parameter T is placed in brackets and serves as a placeholder for the actual type. The compiler recognizes any reference to T within the body of the class and replaces it with the actual type requested. As this statement shows, creating an instance of a generic class is straightforward:
myCollection <string> = new myCollection<string>;

In this case, string is a type argument and specifies that the class is to work with string types only. Note that more than one type parameter may be used, and that the type parameter can be any name, although Microsoft uses (and recommends) single characters in its generic classes.
Although a class may be generic, it can restrict the types that it will accept. This is done by including an optional list of constraints for each type parameter. To declare a constraint, add the where keyword followed by a list of parameter/requirement pairs. The following declaration requires that the type parameter implement the ISerializable and IComparable interfaces:
public class myCollection<T> where

   T:ISerializable,

   T:IComparable

A parameter may have multiple interface constraints and a single class restraint. In addition, there are three special constraints to be aware of:
class— Parameter must be reference type.
struct— Parameter must be value type.
new()— Type parameter must have a parameterless constructor.
An example of a generic class is provided in Listing 3-16. The class implements an array that manages objects of the type specified in the type parameter. It includes methods to add items to the array, compare items, and return an item count. It includes one constraint that restricts the type parameter to a reference type.
Listing 3-16. A Generic Class to Hold Data
using System.Collections.Generic

public class GenStack<T>

   where T:class    // constraint restricts access to ref types

{

   private T[] stackCollection;

   private int count = 0;

   // Constructor

   public GenStack(int size)

   {

      stackCollection = new T[size];

   }

   public void Add(T item)

   {

      stackCollection[count] = item;

      count += 1;

   }

   // Indexer to expose elements in internal array

   public T this[int ndx]

   {

      get

      {

         if (!(ndx < 0 || ndx > count - 1))

            return stackCollection[ndx];

         // Return empty object

         else return (default(T));

      }

   }

   public int ItemCount

   {

      get {return count;}

   }

   public int Compare<C>(T value1, T value2)

   {

      // Case-sensitive comparison: -1, 0(match), 1

      return Comparer<T>.Default.Compare(value1, value2);

   }

}

The following code demonstrates how a client could access the generic class described in Listing 3-16:
// Create instance to hold 10 items of type string

GenStack<string> myStack = new GenStack<string>(10);

myStack.Add("Leslie");

myStack.Add("Joanna");

Console.WriteLine(myStack.ItemCount);  // 2

Console.WriteLine(myStack[1]);         // Joanna

int rel = myStack.Compare<string>("Joanna", "joanna");  // -1

Console.WriteLine(rel.ToString());

Class in C#

Introduction to a C# Class

Figure 3-1 displays a class declaration followed by a body containing typical class members: a constant, fields, a constructor containing initialization code, a property, and a method. Its purpose is to familiarize you with the syntax common to most C# classes and serve as a reference for later examples.

Defining a Class
A class definition consists of an optional attributes list, optional modifiers, the word class followed by the class identifier (name), and an optional list containing a base class or interfaces to be used for inheritance. Following this class declaration is the class body, consisting of the code and class members such as methods and properties.
Syntax for class definition:

[attributes] [modifiers] class  identifier [:baselist]

{class body} [;]


Classes—as do all .NET types—inherit from the System.Object class. This inheritance is implicit and is thus not specified as part of the class definition. As we'll see in the discussion of inheritance, this is important because a class can explicitly inherit from only one class.
Attributes
The optional attribute section consists of a pair of square brackets surrounding a comma-separated list of one or more attributes. An attribute consists of the attribute name followed by an optional list of positional or named arguments. The attribute may also contain an attribute target—that is, the entity to which the attribute applies.
Examples
The attribute section contains an attribute name only:

[ClassDesc]


Single attribute with named argument and positional argument (0):

[ClassDesc(Author="Knuth", 0)]


Multiple attributes can be defined within brackets.:

[ClassDesc(Author="Knuth"), ClassDesc(Author="James")]


Description
Attributes provide a way to associate additional information with a target entity. In our discussion, the target is a newly created class; but attributes may also be associated with methods, fields, properties, parameters, structures, assemblies, and modules. Their simple definition belies a truly innovative and powerful programming tool. Consider the following:
  • An attribute is an instance of a public class. As such, it has fields and properties that can be used to provide rich descriptive information about a target or targets.
  • All compilers that target the Common Language Runtime (CLR) recognize attributes and store information about them in the module's metadata. This is an elegant way to attach information to a program entity that can affect its behavior without modifying its implementation code. An application can then use reflection (a set of types for reading metadata) to read the metadata at runtime and make decisions based on its value.
  • Hundreds of predefined attributes are included in the .NET Framework Class Library (FCL). They are used heavily in dealing with interoperability issues such as accessing the Win32API or allowing .NET applications and COM objects to communicate. They also are used to control compiler operations. The[assembly:CLSComplianttrue)] attribute in Figure 3-1 tells the C# compiler to check the code for CLS compliance.
Core Note
Attributes provide a way to extend the metadata generated by the C# compiler with custom descriptive information about a class or class member.

.NET supports two types of attributes: custom attributes and standard attributes. Custom attributes are defined by the programmer. The compiler adds them to the metadata, but it's up to the programmer to write the reflection code that incorporates this metadata into the program. Standard attributes are part of the .NET Framework and recognized by the runtime and .NET compilers. The Flags attribute that was discussed in conjunction with enums in Chapter 2, "C# Language Fundamentals," is an example of this; another is the conditional attribute, described next.
Conditional Attribute
The conditional attribute is attached to methods only. Its purpose is to indicate whether the compiler should generate Intermediate Language (IL) code to call the method. The compiler makes this determination by evaluating the symbol that is part of the attribute. If the symbol is defined (using the define preprocessor directive), code that contains calls to the method is included in the IL. Here is an example to demonstrate this:
File: attribs.cs (attribs.dll)

#define DEBUG

using System;

using System.Diagnostics;   // Required for conditional attrib.

public class AttributeTest

{

   [Conditional("TRACE")]

   public static void ListTrace()

   { Console.WriteLine("Trace is On"); }

   [Conditional("DEBUG")]

   public static void ListDebug()

   { Console.WriteLine("Debug is On"); }

}


File: attribclient.cs (attribclient.exe)

#define TRACE

using System;

public class MyApp {

   static void Main()

   {

      Console.WriteLine("Testing Method Calls");

      AttributeTest.ListTrace();

      AttributeTest.ListDebug();

   }

}


Executing attribclient yields the following output:

Testing Method Calls

Trace is On


When attribclient is compiled, the compiler detects the existence of the trACE symbol, so the call to ListTrace is included. Because DEBUG is not defined, the call to ListDebug is excluded. The compiler ignores the fact that DEBUG is defined in attribs; its action is based on the symbols defined in the file containing the method calls. Note that a conditional attribute can be used only with methods having a return type of void.
Access Modifiers
The primary role of modifiers is to designate the accessibility (also called scope or visibility) of types and type members. Specifically, a class access modifier indicates whether a class is accessible from other assemblies, the same assembly, a containing class, or classes derived from a containing class.
public
A class can be accessed from any assembly.
protected
Applies only to a nested class (class defined within another class). Access is limited to the container class or classes derived from the container class.
internal
Access is limited to classes in the same assembly. This is the default access.
private
Applies only to a nested class. Access is limited to the container class.
protected internal
The only case where multiple modifiers may be used.
internal
Access is limited to the current assembly or types derived from the containing class.

Core Note
A base class must be at least as accessible as its derived class. The following raises an error:

class  Furniture { }               // default access is internal

public class Sofa : Furniture { }  // error


The error occurs because the Furniture class (internal by default) is less accessible than the derived Sofa class. Errors such as this occur most frequently when a developer relies on a default modifer. This is one reason that modifiers should be included in a declaration.

Abstract, Sealed, and Static Modifiers
In addition to the access modifiers, C# provides a dozen or so other modifiers for use with types and type members. Of these, three can be used with classes: abstract, sealed, and static.
abstract
Indicates that a class is to be used only as a base class for other classes. This means that you cannot create an instance of the class directly. Any class derived from it must implement all of its abstract methods and accessors. Despite its name, an abstract class can possess nonabstract methods and properties.
sealed
Specifies that a class cannot be inherited (used as a base class). Note that .NET does not permit a class to be both abstract and sealed.
static
Specifies that a class contains only static members (.NET 2.0).

Class Identifier
This is the name assigned to the class. The ECMA standard recommends the following guidelines for naming the identifier:
  • Use a noun or noun phrase.
  • Use the Pascal case capitalization style: The first letter in the name and the first letter of each subsequent concatenated word are capitalized—for example, BinaryTree.
  • Use abbreviations sparingly.
  • Do not use a type prefix, such as C, to designate all classes—for example, BinaryTree, not CBinaryTree.
  • Do not use the underscore character.
  • By convention, interface names always begin with I; therefore, do not use I as the first character of a class name unless I is the first letter in an entire word—for example, IntegralCalculator.
Base Classes, Interfaces, and Inheritance
This optional list contains a previously defined class or interface(s) from which a class may derive its behavior and capabilities. The new class is referred to as the derived class, and the class or interface from which it inherits is the base class or interface. A base class must be listed before any interface(s).
Example

// .. FCL Interface and user-defined base class

public interface System.Icomparable

   {Int32 CompareTo(Object object); }

class Furniture {  }

// .. Derived Classes

class Sofa: Furniture { ... }  // Inherits from one base class

// Following inherits from one base class and one interface.

class Recliner: Furniture, IComparable {...}


The C# language does not permit multiple class inheritance, thus the base list can contain only one class. Because there is no limit on the number of inherited interfaces, this serves to increase the role of interfaces in the .NET world.
 

Overview of Class Members

Table 3-1 provides a summary of the types that comprise a .NET class. They can be classified broadly as members that hold data—constants, fields, and properties—and members that provide functionality—the constructor, method, and event. We'll look at each individually.
Table 3-1. Class Members
Member Type
Valid In
Description
Constant
Class, Structure
A symbol that represents an unchanging value. The compiler associates it with the class—not an instance of the class.
Field
Class, Structure
A variable that holds a data value. It may be read-only or read/write.
Property
Class, Structure
Provides access to a value in a class. It uses an accessor that specifies the code to be executed in order to read or write the value. The code to read or write to a property is implemented implicitly by .NET as two separate methods.
Constructor
Class, Structure
C# has three types of constructors:
Instance. Initializes fields when an instance of a class is created.
Private. Commonly used to prevent instances of a class from being created.
Static. Initializes class before any instance is created.
Method
Class, Structure, Interface
A function associated with the class that defines an action or computation.
Events
Class, Structure, Interface
A way for a class or object to notify other classes or objects that its state has changed.
Types
Class, Structure, Interface
Classes, interfaces, structs, delegates.


Member Access Modifiers

The access modifiers used for a class declaration can also be applied to class members. They determine the classes and assemblies that have access to the class. Table 3-2 summarizes the scope of accessibility.
Table 3-2. Summary of Accessibility Provided by Access Modifiers
 
Access Modifiers
Class can be accessed by classes in:
Public
protected
Internal
private
Another assembly
Yes
No
Same assembly
Yes
Yes
Containing class
Yes
Yes
Yes
Yes
Class derived from containing class
Yes
Yes
Yes
No


 

Saturday, 27 October 2012

C# Preprocessing Directives


C# Preprocessing Directives

Preprocessing directives are statements read by the C# compiler during its lexical analysis phase. They can instruct the compiler to include/exclude code or even abort compilation based on the value of preprocessing directives.
A preprocessor directive is identified by the # character that must be the first nonblank character in the line. Blank spaces are permitted before and after the # symbol. Table 2-8 lists the directives that C# recognizes.
Table 2-8. Preprocessing Directives
C# Preprocessing Symbol
Description
#define

#undef

Used to define and undefine a symbol. Defining a symbol makes it evaluate to true when used in a #if directive.
#if

#elif

#else

#endif

Analogues to the C# if, else if, and else statements.
#line
Changes the line number sequence and can identify which file is the source for the line.
#region

#endregion

Used to specify a block of code that you can expand or collapse when using the outlining feature of Visual Studio.NET.
#error

#warning

#error causes the compiler to report a fatal error.
#warning causes the compiler to report a warning and continue processing.


The three most common uses for preprocessing directives are to perform conditional compilation, add diagnostics to report errors and warnings, and define code regions.

Conditional Compilation

The #if related directives are used to selectively determine which code is included during compilation. Any code placed between the #if statement and #endif statement is included or excluded based on whether the #if condition is true or false. This is a powerful feature that is used most often for debug purposes. Here is an example that illustrates the concept:
#define DEBUG

using System;

public class MyApp 

{      

   public static void Main() 

   {

      #if (DEBUG)

         Console.WriteLine("Debug Mode");      

      #else

         Console.WriteLine("Release Mode");

      #endif

   }

}


Any #define directives must be placed at the beginning of the .cs file. A conditional compilation symbol has two states: defined or undefined. In this example, the DEBUG symbol is defined and the subsequent #if (DEBUG) statement evaluates to true. The explicit use of the #define directive permits you to control the debug state of each source file. Note that if you are using Visual Studio, you can specify a Debug build that results in the DEBUG symbol being automatically defined for each file in the project. No explicit #define directive is required.
You can also define a symbol on the C# compile command line using the /Define switch:
csc /Define:DEBUG myproject.cs


Compiling code with this statement is equivalent to including a #Define DEBUG statement in the source code.

Diagnostic Directives

Diagnostic directives issue warning and error messages that are treated just like any other compile-time errors and warnings. The #warning directive allows compilation to continue, whereas the #error terminates it.
#define CLIENT

#define DEBUG

using System;

public class MyApp 

{      

   public static void Main() 

   {

      #if DEBUG && INHOUSE

         #warning Debug is on.  

      #elif DEBUG && CLIENT

         #error Debug not allowed in Client Code.

      #endif

   // Rest of program follows here


In this example, compilation will terminate with an error message since DEBUG and CLIENT are defined.

Code Regions

The region directives are used to mark sections of code as regions. The region directive has no semantic meaning to the C# compiler, but is recognized by Visual Studio.NET, which uses it to hide or collapse code regions. Expect other third-party source management tools to take advantage of these directives.
#region

   // any C# statements

#endregion