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

Loops


Loops

C# provides four iteration statements: while, do, for, and foreach. The first three are the same constructs you find in C, C++, and Java; the foreach statement is designed to loop through collections of data such as arrays.

while loop

Syntax:
while ( boolean expression ) { body }


The statement(s) in the loop body are executed until the boolean expression is false. The loop does not execute if the expression is initially false.
Example:
byte[] r = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF};

int ndx=0;

int totVal = 0;

while (ndx <=6) 

{

   totVal +=    r[ndx];   

   ndx += 1;

}




do loop

Syntax:
do { do-body } while ( boolean expression );


This is similar to the while statement except that the evaluation is performed at the end of the iteration. Consequently, this loop executes at least once.
Example:
byte[] r = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF};

int ndx=0;

int totVal = 0;

do 

{

   totVal += r[ndx];

   ndx += 1;

}

while (ndx <= 6);      


for loop

Syntax:
for ( [initialization]; [termination condition]; [iteration] )

     { for-body }


The for construct contains initialization, a termination condition, and the iteration statement to be used in the loop. All are optional. The initialization is executed once, and then the condition is checked; as long as it is TRue, the iteration update occurs after the body is executed. The iteration statement is usually a simple increment to the control variable, but may be any operation.
Example:
int[] r = {80, 88, 90, 72, 68, 94, 83};

int totVal = 0;

for (int ndx = 0; ndx <= 6; ndx++) {

   totVal += r[ndx];

}


If any of the clauses in the for statement are left out, they must be accounted for elsewhere in the code. This example illustrates how omission of the for-iteration clause is handled:
for   (ndx = 0; ndx < 6; )

{

   totVal += r[ndx];

   ndx++;          // increment here

}


You can also leave out all of the for clauses:
for (;;) { body   }   // equivalent to while(true) { body }


A return, goto, or break statement is required to exit this loop.

foreach loop

Syntax:
foreach ( type identifier in collection )  { body }


The type and identifier declare the iteration variable. This construct loops once for each element in the collection and sets the iteration variable to the value of the current collection element. The iteration variable is read-only, and a compile error occurs if the program attempts to set its value.
For demonstration purposes, we will use an array as the collection. Keep in mind, however, that it is not restricted to an array. There is a useful set of collection classes defined in .NET that work equally well with foreach. We look at those in Chapter 4, "Working with Objects in C#."
Example:
int totVal = 0;

foreach (int arrayVal in r)

{

   totVal += arrayVal;

}


In a one-dimensional array, iteration begins with index 0 and moves in ascending order. In a multi-dimensional array, iteration occurs through the rightmost index first. For example, in a two-dimensional array, iteration begins in the first column and moves across the row. When it reaches the end, it moves to the next row of the first column and iterates that row.

Transferring Control Within a Loop

It is often necessary to terminate a loop, or redirect the flow of statements within the loop body, based on conditions that arise during an iteration. For example, a while (true) loop obviously requires that the loop termination logic exists in the body. Table 2-7 summarizes the principal statements used to redirect the program flow.
Table 2-7. Statements to Exit a Loop or Redirect the Iteration
Statement
Description
Example
break
Redirects program control to the end point of a containing loop construct.
while (true) {

   ndx+=1;

   if (ndx >10) break;

}



continue
Starts a new iteration of enclosing loop without executing remaining statements in loop.
while (ndx <10) {

   ndx +=1;

   if(ndx %2 =1) continue;

   totVal += ndx;

}

goto

identifier;



goto case exp;



goto default;

Directs program control to a label, a case statement within a switch block, or the default statement within a switch block.
The goto may not transfer control into a nested scope—for example, a loop.
public int FindMatch(string myColor)

{

   string[] colorsAvail("blueaqua",

      "red", "green","navyblue");

   int loc;

   int matches=0;

   foreach (colorType in colorsAvail)

   {

      loc = colortype.IndexOf(myColor);

      if (loc >=0) goto Found;

      continue;

Found: 

      matches += 1;

   }   

      return(matches);

}

return

[expression] ;

Returns program control to the method that called the current method. Returns no argument if the enclosing method has a void return type.
public double Area(double w, double l) 

{ 

   return w * l;

}



There are few occasions where the use of a goto statement improves program logic. The goto default version may be useful in eliminating redundant code inside a switch block, but aside from that, avoid its use.

Operators: Arithmetic, Logical, and Conditional

Operators:

Arithmetic, Logical, and Conditional

The C# operators used for arithmetic operations, bit manipulation, and conditional program flow should be familiar to all programmers. This section presents an overview of these operators that is meant to serve as a syntactical reference.

Arithmetic Operators

Table 2-4 summarizes the basic numerical operators. The precedence in which these operators are applied during the evaluation of an expression is shown in parentheses, with 1 being the highest precedence.
Table 2-4. Numerical Operators
Operator
Description
Example
+

-

(3)
Addition
Subtraction
int x = y + 10;
*

/

%

(2)
Multiplication
Division,
Modulo
int x = 60;

int y = 15;

int z = x * y / 2;  // 450

y = x % 29 ;  // remainder is 2

++

--

(1)
Prefix/postfix
Increment/decrement
x = 5;

Console.WriteLine(x++) // x = 5 

Console.WriteLine(++x) // x = 6

~
(1)
Bitwise complement
int x = ~127; // returns -128
>>

<<

(4)
Shift right
Shift left
byte x = 10; // binary 10 is 01010

int result = x << 1; // 20 = 10100

result = x >> 2;     //  5 = 00101


Works with byte, char, short, int, and long
&

|

^

(5-6-7)
Bitwise AND
Bitwise OR
Bitwise XOR
byte x = 12;        //    001100

byte y = 11;        //    001011

int result = x & y; //8 = 001000

result = x ^ y;     //7 = 000111



Core Note
C# does not provide an exponentiation operator. Instead, use the Math.Pow() method to raise a number to a power, and Math.Exp() to raise e to a power.

Conditional and Relational Operators

Relational operators are used to compare two values and determine their relationship. They are generally used in conjunction with conditional operators to form more complex decision constructs. Table 2-5 provides a summary of C# relational and conditional operators.
Table 2-5. Relational and Conditional Boolean Operators
Statement
Description
Example
==

!=

Equality
Inequality
if (x == y) {...}
<

<=

>

>=

Numeric less than
Less than or equal to
Greater than
Greater than or equal to
if (x <= y) {...}
&&

||

Logical AND
Logical OR
if (x == y && y < 30) {...}
If first expression is false, second is not evaluated
&

|

Logical AND
Logical OR
if (x== y | y < 30) {...}
Always evaluates second expression
!
Logical negation
if !(x ==y && y < 30) {...}


Note the two forms of the logical AND/OR operations. The && and || operators do not evaluate the second expression if the first is false—a technique known as short circuit evaluation. The & and | operators always evaluate both expressions. They are used primarily when the expression values are returned from a method and you want to ensure that the methods are called.
In addition to the operators in Table 2-5, C# supports a ?: operator for conditionally assigning a value to a variable. As this example shows, it is basically shorthand for using an if-else statement:
string pass;

int grade=74;

If(grade >= 70) pass="pass"; else pass="fail";

//     expression   ? op1  : op2

pass = (grade >= 70)  ? "pass" : "fail";


If the expression is TRue, the ?: operator returns the first value; if it's false, the second is returned.

Control Flow Statements

The C# language provides if and switch conditional constructs that should be quite familiar to C++ and Java programmers. Table 2-6 provides a summary of these statements.
Table 2-6. Control Flow Statements
Conditional Statement
Example
if (boolean expression) {

   // statements

} else {

   // statements

}

if (bmi < 24.9) {

   weight = "normal";

   riskFactor = 2;

} else {

   weight = "over";

   riskFactor=6;

}

switch (expression) 

{

   case constant expression:

      // statements;

      // break/goto/return()

   case constant expression:

      // statements;

      // break/goto/return()

   default:

      // statements;

      // break/goto/return()

}


  • Constant expression may be an integer, enum value, or string.
  • No "fall through" is permitted. Each case block must end with a statement that transfers control.
switch (ndx)

{

   case 1:

      fabric = "cotton";

      blend = "100%";

      break;

   case 2:  // combine 2 & 3 

   case 3:

      fabric = "cotton";

      blend = "60%";

      break;

   default:  // optional

      fabric = "cotton";

      blend = "50%";

      break;

}



if-else

Syntax:
if ( boolean expression ) statement

if ( boolean expression ) statement1 else statement2

C# if statements behave as they do in other languages. The only issue you may encounter is how to format the statements when nesting multiple if-else clauses.
// Nested if statements

if (age > 16)                         if (age > 16)

{                                        if (sex == "M")

   if (sex == "M")                          type = "Man";

   {                                     else

      type = "Man";                         type = "Woman" ;

   } else {                           else

      type = "Woman" ;                   type = "child";

   }

} else {  

   type = "child";

}


Both code segments are equivalent. The right-hand form takes advantage of the fact that curly braces are not required to surround single statements; and the subordinate if clause is regarded as a single statement, despite the fact that it takes several lines. The actual coding style selected is not as important as agreeing on a single style to be used.

switch

Syntax:
switch( expression ) {switch block}


The expression is one of the int types, a character, or a string. The switch block consists of case labels—and an optional default label—associated with a constant expression that must implicitly convert to the same type as the expression. Here is an example using a string expression:
// switch with string expression

using System;

public class MyApp 

{

   static void Main(String[] args)

   {

      switch (args[0]) 

      {

         case "COTTON":   // is case sensitive

         case "cotton":

              Console.WriteLine("A good natural fiber.");

              goto case "natural";

         case "polyester":

              Console.WriteLine("A no-iron synthetic fiber.");

              break;

         case "natural":

              Console.WriteLine("A Natural Fiber. ");

              break;

         default:

              Console.WriteLine("Fiber is unknown.");

              break;

      }

   }

}


The most important things to observe in this example are as follows:
  • C# does not permit execution to fall through one case block to the next. Each case block must end with a statement that transfers control. This will be a break, goto. or return statement.
  • Multiple case labels may be associated with a single block of code.
  • The switch statement is case sensitive; in the example, "Cotton" and "COTTON" represent two different values.

Primitives Data Types

Primitives-

The next three sections of this chapter describe features that you'll find in most programming languages: variables and data types, operators, expressions, and statements that control the flow of operations. The discussion begins with primitives. As the name implies, these are the core C# data types used as building blocks for more complex class and structure types. Variables of this type contain a single value and always have the same predefined size. Table 2-3 provides a formal list of primitives, their corresponding core data types, and their sizes.
Table 2-3. C# Primitive Data Types
C# Primitive Type
FCL Data Type
Description
object
System.Object
Ultimate base type of all other types.
string
System.String
A sequence of Unicode characters.
decimal
System.Decimal
Precise decimal with 28 significant digits.
bool
System.Boolean
A value represented as true or false.
char
System.Char
A 16-bit Unicode character.
byte
System.Byte
8-bit unsigned integral type.
sbyte
System.SByte
8-bit signed integral type.
short
System.Int16
16-bit signed integral type.
int
System.Int32
32-bit signed integral type.
long
System.Int64
64-bit signed integral type.
ushort
System.UInt16
16-bit unsigned integral type.
uint
System.UInt32
32-bit unsigned integral type.
ulong
System.UIint64
64-bit unsigned integral type.
single (float)
System.Single
Single-precision floating-point type.
double
System.Double
Double-precision floating-point type.


As the table shows, primitives map directly to types in the base class library and can be used interchangeably. Consider these statements:
System.Int32 age = new System.Int32(17);

int age = 17; 

System.Int32 age = 17;


They all generate exactly the same Intermediate Language (IL) code. The shorter version relies on C# providing the keyword int as an alias for the System.Int32 type. C# performs aliasing for all primitives.
Here are a few points to keep in mind when working with primitives:
  • The keywords that identify the value type primitives (such as int) are actually aliases for an underlying structure (struct type in C#). Special members of these structures can be used to manipulate the primitives. For example, the Int32 structure has a field that returns the largest 32-bit integer and a method that converts a numeric string to an integer value:
    int iMax = int.MaxValue;     // Return largest integer 
    
    int pVal = int.Parse("100"); // converts string to int
    
    

    The C# compiler supports implicit conversions if the conversion is a "safe" conversion that results in no loss of data. This occurs when the target of the conversion has a greater precision than the object being converted, and is called a widening conversion. In the case of a narrowing conversion, where the target has less precision, the conversion must have explicit casting. Casting is used to coerce, or convert, a value of one type into that of another. This is done syntactically by placing the target data type in parentheses in front of the value being converted: int i = (int)y;.
    short i16 = 50;    // 16-bit integer
    
    int i32 = i16;     // Okay: int has greater precision
    
    i16 = i32;         // Fails: short is 16 bit, int is 32
    
    i16 = (short) i32; // Okay since casting used
    
    

  • Literal values assigned to the types float, double, and decimal require that their value include a trailing letter: float requires F or f; double has an optional D or d; and decimal requires M or m.
    decimal pct = .15M; // M is required for literal value
    
    
The remainder of this section offers an overview of the most useful primitives with the exception of string, which is discussed later in the chapter.

decimal

The decimal type is a 128-bit high-precision floating-point number. It provides 28 decimal digits of precision and is used in financial calculations where rounding cannot be tolerated. This example illustrates three of the many methods available to decimal type. Also observe that when assigning a literal value to a decimal type, the M suffix must be used.
decimal iRate = 3.9834M;         // decimal requires M 

iRate = decimal.Round(iRate,2);  // Returns 3.98

decimal dividend = 512.0M;

decimal divisor = 51.0M;

decimal p = decimal.Parse("100.05");

// Next statement returns remainder = 2

decimal rem = decimal.Remainder(dividend,divisor);


bool

The only possible values of a bool type are true and false. It is not possible to cast a bool value to an integer—for example, convert true to a 1, or to cast a 1 or 0 to a bool.
bool bt = true;

string bStr = bt.ToString(); // returns "true"

bt = (bool) 1;               // fails


char

The char type represents a 16-bit Unicode character and is implemented as an unsigned integer. A char type accepts a variety of assignments: a character value placed between individual quote marks (' '); a casted numeric value; or an escape sequence. As the example illustrates, char also has a number of useful methods provided by the System.Char structure:
myChar =  'B';       // 'B' has an ASCII value of 66

myChar = (char) 66;  // Equivalent to 'B'

myChar = '\u0042';   // Unicode escape sequence

myChar = '\x0042';   // Hex escape sequence

myChar = '\t';       // Simple esc sequence:horizontal tab

bool bt;

string pattern = "123abcd?";

myChar = pattern[0];                  // '1'

bt = char.IsLetter(pattern,3);        // true  ('a')

bt = char.IsNumber(pattern,3);        // false

bt = char.IsLower(pattern,0);         // false ('1')

bt = char.IsPunctuation(pattern,7);   // true  ('?')

bt = char.IsLetterOrDigit(pattern,1); // true

bt = char.IsNumber(pattern,2);        // true  ('3')

string kstr="K";

char k = char.Parse(kstr);


byte, sbyte

A byte is an 8-bit unsigned integer with a value from 0 to 255. An sbyte is an 8-bit signed integer with a value from –128 to 127.
byte[] b = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF};

string s = b[4].ToString(); // returns 170

char myChar = (char) b[3];


short, int, long

These represent 16-, 32-, and 64-bit signed integer values, respectively. The unsigned versions are also available (ushort, uint, ulong).
short i16 = 200;

i16 = 0xC8 ;     // hex value for 200

int i32 = i16;   // no casting required 


single, double

These are represented in 32-bit single-precision and 64-bit double-precision formats. In .NET 1.x, single is referred to as float.
  • The single type has a value range of 1.5 x 10 –45 to 3.4 x 1038 with 7-decimal digit precision.
  • The double type has a value range of 5 x 10–324 to 1.7 x 10308 with 15- to 16-decimal digit precision.
  • Floating-point operations return NaN (Not a Number) to signal that the result of the operation is undefined. For example, dividing 0.0 by 0.0 results in NaN.
  • Use the System.Convert method when converting floating-point numbers to another type.
float xFloat = 24567.66F;

int xInt = Convert.ToInt32(xFloat);  // returns 24567

int xInt2 = (int) xFloat;

if(xInt == xInt2) {  }               // False

string xStr = Convert.ToString(xFloat);

single zero = 0;

if (Single.IsNaN(0 / zero)) {  }     // True

double xDouble = 124.56D;


Note that the F suffix is used when assigning a literal value to a single type, and D is optional for a double type.

Using Parse and TryParse to Convert a Numeric String

The primitive numeric types include Parse and tryParse methods that are used to convert a string of numbers to the specified numeric type. This code illustrates:
short shParse  = Int16.Parse("100");

int iParse     = Int32.Parse("100");

long lparse    = Int64.Parse("100");

decimal dParse = decimal.Parse("99.99");

float sParse   = float.Parse("99.99");

double dbParse = double.Parse("99.99");


TRyParse, introduced in .NET 2.0, provides conditional parsing. It returns a boolean value indicating whether the parse is successful, which provides a way to avoid formal exception handling code. The following example uses an Int32 type to demonstrate the two forms of tryParse:
int result;

// parse string and place result in result parameter

bool ok = Int32.TryParse("100", out result); 

bool ok = Int32.TryParse("100", NumberStyles.Integer, null,

                         out result);


In the second form of this method, the first parameter is the text string being parsed, and the second parameter is a NumberStyles enumeration that describes what the input string may contain. The value is returned in the fourth parameter.

Primitives-

The next three sections of this chapter describe features that you'll find in most programming languages: variables and data types, operators, expressions, and statements that control the flow of operations. The discussion begins with primitives. As the name implies, these are the core C# data types used as building blocks for more complex class and structure types. Variables of this type contain a single value and always have the same predefined size. Table 2-3 provides a formal list of primitives, their corresponding core data types, and their sizes.
Table 2-3. C# Primitive Data Types
C# Primitive Type
FCL Data Type
Description
object
System.Object
Ultimate base type of all other types.
string
System.String
A sequence of Unicode characters.
decimal
System.Decimal
Precise decimal with 28 significant digits.
bool
System.Boolean
A value represented as true or false.
char
System.Char
A 16-bit Unicode character.
byte
System.Byte
8-bit unsigned integral type.
sbyte
System.SByte
8-bit signed integral type.
short
System.Int16
16-bit signed integral type.
int
System.Int32
32-bit signed integral type.
long
System.Int64
64-bit signed integral type.
ushort
System.UInt16
16-bit unsigned integral type.
uint
System.UInt32
32-bit unsigned integral type.
ulong
System.UIint64
64-bit unsigned integral type.
single (float)
System.Single
Single-precision floating-point type.
double
System.Double
Double-precision floating-point type.


As the table shows, primitives map directly to types in the base class library and can be used interchangeably. Consider these statements:
System.Int32 age = new System.Int32(17);

int age = 17; 

System.Int32 age = 17;


They all generate exactly the same Intermediate Language (IL) code. The shorter version relies on C# providing the keyword int as an alias for the System.Int32 type. C# performs aliasing for all primitives.
Here are a few points to keep in mind when working with primitives:
  • The keywords that identify the value type primitives (such as int) are actually aliases for an underlying structure (struct type in C#). Special members of these structures can be used to manipulate the primitives. For example, the Int32 structure has a field that returns the largest 32-bit integer and a method that converts a numeric string to an integer value:
    int iMax = int.MaxValue;     // Return largest integer 
    
    int pVal = int.Parse("100"); // converts string to int
    
    

    The C# compiler supports implicit conversions if the conversion is a "safe" conversion that results in no loss of data. This occurs when the target of the conversion has a greater precision than the object being converted, and is called a widening conversion. In the case of a narrowing conversion, where the target has less precision, the conversion must have explicit casting. Casting is used to coerce, or convert, a value of one type into that of another. This is done syntactically by placing the target data type in parentheses in front of the value being converted: int i = (int)y;.
    short i16 = 50;    // 16-bit integer
    
    int i32 = i16;     // Okay: int has greater precision
    
    i16 = i32;         // Fails: short is 16 bit, int is 32
    
    i16 = (short) i32; // Okay since casting used
    
    

  • Literal values assigned to the types float, double, and decimal require that their value include a trailing letter: float requires F or f; double has an optional D or d; and decimal requires M or m.
    decimal pct = .15M; // M is required for literal value
    
    
The remainder of this section offers an overview of the most useful primitives with the exception of string, which is discussed later in the chapter.

decimal

The decimal type is a 128-bit high-precision floating-point number. It provides 28 decimal digits of precision and is used in financial calculations where rounding cannot be tolerated. This example illustrates three of the many methods available to decimal type. Also observe that when assigning a literal value to a decimal type, the M suffix must be used.
decimal iRate = 3.9834M;         // decimal requires M 

iRate = decimal.Round(iRate,2);  // Returns 3.98

decimal dividend = 512.0M;

decimal divisor = 51.0M;

decimal p = decimal.Parse("100.05");

// Next statement returns remainder = 2

decimal rem = decimal.Remainder(dividend,divisor);


bool

The only possible values of a bool type are true and false. It is not possible to cast a bool value to an integer—for example, convert true to a 1, or to cast a 1 or 0 to a bool.
bool bt = true;

string bStr = bt.ToString(); // returns "true"

bt = (bool) 1;               // fails


char

The char type represents a 16-bit Unicode character and is implemented as an unsigned integer. A char type accepts a variety of assignments: a character value placed between individual quote marks (' '); a casted numeric value; or an escape sequence. As the example illustrates, char also has a number of useful methods provided by the System.Char structure:
myChar =  'B';       // 'B' has an ASCII value of 66

myChar = (char) 66;  // Equivalent to 'B'

myChar = '\u0042';   // Unicode escape sequence

myChar = '\x0042';   // Hex escape sequence

myChar = '\t';       // Simple esc sequence:horizontal tab

bool bt;

string pattern = "123abcd?";

myChar = pattern[0];                  // '1'

bt = char.IsLetter(pattern,3);        // true  ('a')

bt = char.IsNumber(pattern,3);        // false

bt = char.IsLower(pattern,0);         // false ('1')

bt = char.IsPunctuation(pattern,7);   // true  ('?')

bt = char.IsLetterOrDigit(pattern,1); // true

bt = char.IsNumber(pattern,2);        // true  ('3')

string kstr="K";

char k = char.Parse(kstr);


byte, sbyte

A byte is an 8-bit unsigned integer with a value from 0 to 255. An sbyte is an 8-bit signed integer with a value from –128 to 127.
byte[] b = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF};

string s = b[4].ToString(); // returns 170

char myChar = (char) b[3];


short, int, long

These represent 16-, 32-, and 64-bit signed integer values, respectively. The unsigned versions are also available (ushort, uint, ulong).
short i16 = 200;

i16 = 0xC8 ;     // hex value for 200

int i32 = i16;   // no casting required 


single, double

These are represented in 32-bit single-precision and 64-bit double-precision formats. In .NET 1.x, single is referred to as float.
  • The single type has a value range of 1.5 x 10 –45 to 3.4 x 1038 with 7-decimal digit precision.
  • The double type has a value range of 5 x 10–324 to 1.7 x 10308 with 15- to 16-decimal digit precision.
  • Floating-point operations return NaN (Not a Number) to signal that the result of the operation is undefined. For example, dividing 0.0 by 0.0 results in NaN.
  • Use the System.Convert method when converting floating-point numbers to another type.
float xFloat = 24567.66F;

int xInt = Convert.ToInt32(xFloat);  // returns 24567

int xInt2 = (int) xFloat;

if(xInt == xInt2) {  }               // False

string xStr = Convert.ToString(xFloat);

single zero = 0;

if (Single.IsNaN(0 / zero)) {  }     // True

double xDouble = 124.56D;


Note that the F suffix is used when assigning a literal value to a single type, and D is optional for a double type.

Using Parse and TryParse to Convert a Numeric String

The primitive numeric types include Parse and tryParse methods that are used to convert a string of numbers to the specified numeric type. This code illustrates:
short shParse  = Int16.Parse("100");

int iParse     = Int32.Parse("100");

long lparse    = Int64.Parse("100");

decimal dParse = decimal.Parse("99.99");

float sParse   = float.Parse("99.99");

double dbParse = double.Parse("99.99");


TRyParse, introduced in .NET 2.0, provides conditional parsing. It returns a boolean value indicating whether the parse is successful, which provides a way to avoid formal exception handling code. The following example uses an Int32 type to demonstrate the two forms of tryParse:
int result;

// parse string and place result in result parameter

bool ok = Int32.TryParse("100", out result); 

bool ok = Int32.TryParse("100", NumberStyles.Integer, null,

                         out result);


In the second form of this method, the first parameter is the text string being parsed, and the second parameter is a NumberStyles enumeration that describes what the input string may contain. The value is returned in the fourth parameter.

C# Get Started

C# Language Fundamentals

Topics
Overview of a C# Program: In addition to the basic elements that comprise a C# program, a developer needs to be aware of other .NET features such as commenting options and recommended naming conventions.
  • Primitives: Primitives are the basic data types defined by the FCL to represent numbers, characters, and dates.
  • Operators: C# uses traditional operator syntax to perform arithmetic and conditional operations.
  • Program Flow Statements: Program flow can be controlled using if and switch statements for selection; and while, do, for, and foreach clauses for iteration.
  • String: The string class supports the expected string operations: concatenation, extracting substrings, searching for instances of a character pattern, and both case sensitive and insensitive comparisons.
  • Enums: An enumeration is a convenient way to assign descriptions that can be used to reference an underlying set of values.
  • Using Arrays: Single- or multi-dimensional arrays of any type can be created in C#. After an array is created, the System.Array class can be used to sort and copy the array.
  • Reference and Value Types: All types in .NET are either a value or reference type. It is important to understand the differences and how they can affect a program's performance.

2.1. The Layout of a C# Program

Figure 2-1 illustrates some of the basic features of a C# program.
Figure 2-1. Basic elements of a C# program


The code in Figure 2-1 consists of a class MyApp that contains the program logic and a class Apparel that contains the data. The program creates an instance of Apparel and assigns it to myApparel. This object is then used to print the values of the class members FabType and Price to the console. The important features to note include the following:
  1. The using statement specifies the namespace System. Recall from Chapter 1, "Introduction to .NET and C#," that the .NET class libraries are organized into namespaces and that the System namespace contains all of the simple data types. The using statement tells the compiler to search this namespace when resolving references, making it unnecessary to use fully qualified names. For example, you can refer to label rather than System.Web.UI.WebControls.Label.
  2. All programming logic and data must be contained within a type definition. All program logic and data must be embedded in a class, structure, enum, interface, or delegate. Unlike Visual Basic, for instance, C# has no global variable that exists outside the scope of a type. Access to types and type members is strictly controlled by access modifiers. In this example, the access modifier public permits external classes—such as MyApp—to access the two members of the Apparel class.
  3. A Main() method is required for every executable C# application. This method serves as the entry point to the application; it must always have the static modifier and the M must be capitalized. Overloaded forms of Main()define a return type and accept a parameter list as input.
    Return an integer value:
    static int Main()
    
    {
    
       return 0; // must return an integer value
    
    }
    
    

    Receive a list of command-line arguments as a parameter and return an integer value:
    static int Main(string[] args)
    
    {
    
       // loop through arguments
    
       foreach(string myArg in args)
    
          Console.WriteLine(myArg);
    
       return 0;
    
    }
    
    

    The parameter is a string array containing the contents of the command line used to invoke the program. For example, this command line executes the program MyApparel and passes it two parameter values:
    C:\> MyApparel 5 6
    
    
Core Note
The contents of the command line are passed as an argument to the Main() method. The System.Environment.CommandLine property also exposes the command line's contents.

General C# Programming Notes

Case Sensitivity
All variable and keywords are distinguished by case sensitivity. Replace class with Class in Figure 2-1 and the code will not compile.
Naming Conventions
The ECMA standard provides naming convention guidelines to be followed in your C# code. In addition to promoting consistency, following a strict naming policy can minimize errors related to case sensitivity that often result from undisciplined naming schemes. Table 2-1 summarizes some of the more important recommendations.
Table 2-1. C# Naming Conventions
Type
Case
Notes and Examples
Class
Pascal
  • Use noun or noun phrases.
  • Try to avoid starting with I because this is reserved for interfaces.
  • Do not use underscores.
Constant
Pascal
public const double GramToPound = 454.0 ;
Enum Type
Pascal
  • Use Pascal case for the enum value names.
  • Use singular name for enums.
public enum WarmColor { Orange, Yellow, Brown}
Event
Pascal
  • The method that handles events should have the suffix EventHandler.
  • Event argument classes should have the suffix EventArgs.
Exception
Pascal
  • Has suffix Exception.
Interface
Pascal
  • Has prefix of I.
IDisposable
Local Variable
Camel
  • Variables with public access modifier use Pascal
int myIndex.
Method
Pascal
  • Use verb or verb phrases for name.
Namespace
Pascal
  • Do not have a namespace and class with the same name.
  • Use prefixes to avoid namespaces having the same name. For example, use a company name to categorize namespaces developed by that company.
Acme.GraphicsLib
Property
Pascal
  • Use noun or noun phrase.
Parameter
Camel
  • Use meaningful names that describe the parameter's purpose.


Note that the case of a name may be based on two capitalization schemes:
  1. Pascal. The first character of each word is capitalized (for example, MyClassAdder).
  2. Camel. The first character of each word, except the first, is capitalized (for example, myClassAdder).
The rule of thumb is to use Pascal capitalization everywhere except with parameters and local variables.
Commenting a C# Program
The C# compiler supports three types of embedded comments: an XML version and the two single-line (//) and multi-line (/* */) comments familiar to most programmers:
//   for a single line 

/*   for one or more lines

                      */

/// <remarks> XML comment describing a class </remarks>


An XML comment begins with three slashes (///) and usually contains XML tags that document a particular aspect of the code such as a structure, a class, or class member. The C# parser can expand the XML tags to provide additional information and export them to an external file for further processing.

Table 2-2. XML Documentation Tags
Tag
Description
<example>
Text illustrating an example of using a particular program feature goes between the beginning and ending tags.
<exception cref="Excep">
cref attribute contains name of exception.
///<exceptioncref="NoParmException">

</exception>

<include file="myXML">
file attribute is set to name of another XML file that is to be included in the XML documentation produced by this source code.
<param name="parm1">
name attribute contains the name of the parameter.
<permission cref= "">
Most of the time this is set to the following:
///<permissioncref="System.Security.Permis-

sionSet"> </permission>

<remarks>
Provides additional information about a type not found in the <summary> section.
<returns>
Place a textual description of what is returned from a method or property between the beginning and ending tags.
<seealso cref="price">
The cref attribute is set to the name of an associated type, field, method, or other type member.
<summary>
Contains a class description; is used by IntelliSense in VisualStudio.NET.


The value of the XML comments lies in the fact that they can be exported to a separate XML file and then processed using standard XML parsing techniques. You must instruct the compiler to generate this file because it is not done by default.
The following line compiles the source code consoleapp.cs and creates an XML file consoleXML:
C:\> csc consoleapp.cs /doc:consoleXML.xml

C# Language Fundamentals

Topics
Overview of a C# Program: In addition to the basic elements that comprise a C# program, a developer needs to be aware of other .NET features such as commenting options and recommended naming conventions.
  • Primitives: Primitives are the basic data types defined by the FCL to represent numbers, characters, and dates.
  • Operators: C# uses traditional operator syntax to perform arithmetic and conditional operations.
  • Program Flow Statements: Program flow can be controlled using if and switch statements for selection; and while, do, for, and foreach clauses for iteration.
  • String: The string class supports the expected string operations: concatenation, extracting substrings, searching for instances of a character pattern, and both case sensitive and insensitive comparisons.
  • Enums: An enumeration is a convenient way to assign descriptions that can be used to reference an underlying set of values.
  • Using Arrays: Single- or multi-dimensional arrays of any type can be created in C#. After an array is created, the System.Array class can be used to sort and copy the array.
  • Reference and Value Types: All types in .NET are either a value or reference type. It is important to understand the differences and how they can affect a program's performance.

Thursday, 25 October 2012

SQL XML .NET Data Provider


SQL XML .NET Data Provider

SqlXmlCommand belongs to Microsoft.Data.SqlXml namespace, which is not part of .NET framework. The extra functionality SqlXmlCommand provides are: you can send a XPATH query instead of a SELECT SQL query to database to retrieve data, and submit changes to database using a diffgram XML document.
When you provide a XPATH to the command, it converts it to a “FOR XML” SQL query. When you submit a diffgram, the command generates a batch of SQL queries wrapped in a transaction. In both cases the command needs to know the schema of the table to be able to generate those SQL queries, so you need to provide the command with a XSD file:
' Retrieve data using XPATH
Dim cmd As New SqlXmlCommand(“Orders[CustomerID=’GROSR’]”, strConn)
cmd.SchemaPath = “C:\MySchema.xsd”
cmd.CommandType = SqlXmlCommandType.XPath
Dim rdr As XmlReader = cmd.ExecuteXmlReader()
mds.ReadXml(rdr)

' Do some changes

' Write the changed dataset into a DiffGram
mds.WriteXml(“C:\MyDiffGram.xml”XmlWriteMode.DiffGram)

' Submit the DiffGram
cmd = New SqlXmlCommand(strConn)
cmd.SchemaPath = “C:\MySchema.xsd”
cmd.CommandType = SqlXmlCommandType.DiffGram
cmd.CommandStream = New FileStream(“C:\MyDiffGram.xml”, FileMode.Open, FileAccess.Read)
cmd.ExecuteNonQuery