Saturday, October 15, 2011

- C# Programming Constructs

Every executable C# application must contain a class defining  a Main() method (the class aka application object, which specify the entry point of the application. Keep in mind a single executable application may have more than one application object. Programmer must inform the compiler which Main() method should be used as entry point through one of below ways:
  1. Command line: compiler /main
  2. Visual Studio 2010 project properties:  Application tab-> Startup Object
static int Main(string[] args)
Main() method needs to be static, static members are scoped to the class level (rather than the object level) and they can be invoked without creating a new class instance.
In addition Main() method has a single parameter which happens to be an array of strings (string[] args). This parameter may contain any number of incoming command line arguments. Command line arguments can be added after *.exe file through command prompt (e.g. test.exe -arg1 -arg2) or via Debug tab of project properties (below picture)
Command line arguments

One way to access argument is string[] args parameter of MainI() method and another using Environment.GetCommandLineArgs() which returns string[] as well however the first index identifies the name of the application itself.

Return type int is usually used for returning the error code returning the value 0 indicates the program has terminated successfully (in case of void return type the program automatically returns 0. On Windows operating system , an application's return value is stored within a system environment variable named %ERRORLEVEL%, the value is obtainable using the static System.Diagnostics.Process.ExitCode property. Here is an example of batch file to the return value for outputText.exe you need to locate the batch file in same folder as *.exe file and run the batch file :

@echo off
rem A batch file for OutputTest.exe
rem which captures the app's return value.
outputTest
@if "%ERRORLEVEL%" == "0" goto success
:fail
  echo outputTest has failed!
  echo return value = %ERRORLEVEL%
  goto end
:success
  echo outputTest has succeeded!
  echo return value = %ERRORLEVEL%
  goto end
:end
  echo All Done.
 pause rem wait for user press any key

 Main() method is implicitly private to limit other application directly invoke the entry point of another. However it may also defines as public.

Some Additional Members of the System.Environment:
Environment.GetLogicalDrives() returns an array of string include drives on the machine
Environment.OsVersion Operating System Version
Environment.ProcessorCount Number of processors
Environment.Version .NET version
Environment.MachineName Computer name
Environment.NewLine Gets the newline symbol for the current environment
Environment.StackTrace Current stack trace information for the application
Environment.SystemDirectory
Environment.Username Name of the user which starts the application

System.Console Class:
CUI ( Console User Interface ). Here is some of System.Console members:
Beep() emit a beep of specified frequency and duration  (e.g Console.Beep( 500, 1000))
BackgroundColor (e.g. Console.BackgroundColor = ConsoleColor.Yellow)
ForegroundColor
BufferHeight height of the console's buffer area.
BufferWidth width of the console's buffer area.
Title
WindowHight control the dimensions of the console in relation to the established buffer
WindowWidth control the dimensions of the console in relation to the established buffer
WindowTop
WindowLeft
Clear()

Formatting Console Output / string.Format():
Console.WriteLine("{3}, {0}, {2}, {1}, {0}, {0}", 0, 11, 22, 33);
Output: 33, 0, 22, 11, 0, 0

Formatting Numerical Data:
Here is a collection of most common formatting options:
C (currency), D (decimal), E (exponential), F (fixed-point), G (general), N (basic numerical formatting), X (hexadecimal)


Console.WriteLine("C format:  {0:C}" , 99999);
Console.WriteLine("D9 format: {0:D9}", 99999);
Console.WriteLine("F3 format: {0:F3}", 99999);
Console.WriteLine("N format:  {0:N}" , 99999);
Console.WriteLine("E format:  {0:E}" , 99999);
Console.WriteLine("e format:  {0:e}" , 99999);
Console.WriteLine("X format:  {0:X}" , 99999);
Console.WriteLine("x format:  {0:x}" , 99999);





For more information refer to Standard Numeric Format Strings and Custom Numeric Format Strings
Above formatting syntax can be used when calling the static string.Format() method. Notice string.Format returns a new string object, which is formatted according to the provided flags.

String.Format Align:
  •  To align string to the left (spaces on the right) use formatting pattern with comma (,) followed by a negative number of characters.
  • To right alignment use a positive number.
Example:

Console.WriteLine("|{0}|{1}|", 0, 1);
Console.WriteLine("|{0,-10}|{1,10}|", 0, 1);
Console.WriteLine("|{0,10}|{1,-10}|", 0, 1);
String alignment example output

Data Types:
Data Type
All numerical types (such as short or int) map to a corresponding structure in the System name space Which are value type and allocate on the stack and they must be initialized before using them. On the other hand string and object are reference type and allocated on the managed heap or garbage-collected heap .
Types (C# Programming Guide)
Intrinsic Data Types support default constructor which allow you to create a variable using new keyword and automatically sets the variable to its default value (e.g. Boolean "false", Numeric "0", etc)
As it have been displayed in above picture all System.valueType are inherited from System.Object and they can use the functionality of parent class. Here we go through some:

Console.WriteLine("########## System.Object Functionality #########");
Console.WriteLine();
Console.WriteLine("33.GetHashCode() = {0}", 33.GetHashCode());
Console.WriteLine("33.Equals(23) = {0}", 33.Equals(55));
Console.WriteLine("33.ToString() = {0}", 33.ToString());
Console.WriteLine("33.GetType() = {0}", 33.GetType());
Console.WriteLine();
Console.WriteLine();

Console.WriteLine("##########  Data type Functionality #########");
Console.WriteLine();
Console.WriteLine("Max of int: {0}", int.MaxValue);
Console.WriteLine("Min of int: {0}", int.MinValue);
Console.WriteLine("Max of double: {0}", double.MaxValue);
Console.WriteLine("Min of double: {0}", double.MinValue);
Console.WriteLine("double.Epsilon: {0}", double.Epsilon);
Console.WriteLine("double.PositiveInfinity: {0}", double.PositiveInfinity);
Console.WriteLine("double.NegativeInfinity: {0}", double.NegativeInfinity);
Console.WriteLine("bool.FalseString: {0}", bool.FalseString);
Console.WriteLine("bool.TrueString: {0}", bool.TrueString);
Console.WriteLine();
Console.WriteLine();

Console.WriteLine("##########  char type Functionality ##########");
Console.WriteLine();
char myChar = 'A';
Console.WriteLine("char.IsDigit('A'): {0}", char.IsDigit(myChar));
Console.WriteLine("char.IsLetter('A'): {0}", char.IsLetter(myChar));
Console.WriteLine("char.IsWhiteSpace('Hello world', 4): {0}", char.IsWhiteSpace("Hello world", 4));
Console.WriteLine("char.IsWhiteSpace('Hello world', 5): {0}", char.IsWhiteSpace("Hello world", 5));
Console.WriteLine("char.IsPunctuation('!'): {0}", char.IsPunctuation('!'));
Console.WriteLine(); 

Object, Data type and char type functionality
String and char are both Unicode. String is set of contiguous characters, while the char can is single slot in a string.
Parse Value from String Data:
This could be really useful to get data from input and convert to desirable format (e.g numerical), some example:

Console.WriteLine("########## Data type parsing ##########");
Console.WriteLine();
bool BoolData = bool.Parse("True");
Console.WriteLine("Value of BoolData: {0}", BoolData);
double DoubleData = double.Parse("99.884");
Console.WriteLine("Value of DoubleData: {0}", DoubleData);
int IntData = int.Parse("8");
Console.WriteLine("Value of IntData: {0}", IntData);
char CharData = Char.Parse("X");
Console.WriteLine("Value of CharData: {0}", CharData);
Console.WriteLine();

Data type parsing
System.DateTime (date and time value) and System.TimeSpan (define and transform unit of time) are both types defined within System namespace which they don't have any C# keyword. Here is some example:

Console.WriteLine("########## Dates and Times ##########");
Console.WriteLine();
DateTime date = new DateTime(2012, 9, 30);//(year, month, day)
// What day of the month is this?
Console.WriteLine("The day of {0} is {1}", date.Date, date.DayOfWeek);
date = date.AddMonths(2);  // Month is now November.
Console.WriteLine("Daylight savings: {0}", date.IsDaylightSavingTime());

TimeSpan time_span = new TimeSpan(4, 30, 0); // (hours, minutes, seconds)
Console.WriteLine(time_span);
Console.WriteLine(time_span.Subtract(new TimeSpan(0, 20, 0))); // Subtract 20 minutes

DataTime and TimeSpan
System.Numerics Namespace (.NET 4.0) contains BigInteger and Complex structure. BigInteger data type does not constrained by a fixed upper or lower limit. Complex data type allows you to model mathematically complex numerical data (e.g., imaginary data, hyperbolic tangents). You may refer to this link for more info about Complex Structure. Pay attention that you need to add the reference of System.Numeric.dll in to your project before using above structures.
One way to establish the massive numerical value as a text literal, which can be converted into a BigInteger variable through the static Parse() method or pass in a byte array directly to constructor. The data of BigInteger is immutable and you can not change the value after assign a value to it. However BigInteger class contains some methods which will return new BigInteger objects based on your data modifications (e.g. Multiply() method). Below there is an example to illustrate the BigInteger data type.

Console.WriteLine("#################### Use BigInteger #######################");
Console.WriteLine();
BigInteger bigg_integer = BigInteger.Parse("666666666666666666666666666666");
Console.WriteLine("bigg_integer is {0}", bigg_integer);
Console.WriteLine("bigg_integer is even?: {0}", bigg_integer.IsEven);
Console.WriteLine("bigg_integer is power of 2?: {0}", bigg_integer.IsPowerOfTwo);
BigInteger big_integer2 = BigInteger.Multiply(bigg_integer, BigInteger.Parse("33333333333333333333333333333"));
BigInteger big_integer3 = bigg_integer * big_integer2;
Console.WriteLine("bigg_integer2 is {0}", big_integer2);
Console.WriteLine("bigg_integer3 is {0}", big_integer3);
BigInteger example Output
String Data:
Let's go through some useful members of System.String first:
  • Length :        returns length of the current string
  • Compare():  compare two strings
  • Contains():   determines whether a string contains a specific substring
  • Equals():      determines whether two string objects contain identical character data
  • Format():     static method which formats the string using other primitives
  • Insert():        insert string within a given string  
  • PadLeft():    pad string with some character
  • PadRight():
  • Remove() :   returns a copy of string with removed specified string
  • Replace():    returns a copy of string with replaced specified string
  • Split():         returns a String array containing the substrrings in this instance that are delimited by                              elements of a specified char array or string array.
  • Trim():         removes all occurrences of a set of specified characters from beginning and end of string
  • ToUpper():  create a copy of uppercase string
  • ToLower():  create a copy of lowercase string
Here is an example containing some of above methods:

Console.WriteLine("############## String functionality #######################");
Console.WriteLine();
string my_string = "My String";
Console.WriteLine("my_string: {0}", my_string);
Console.WriteLine("my_string has {0} characters.", my_string.Length);
Console.WriteLine("my_string in UPPERCASE: {0}", my_string.ToUpper());
Console.WriteLine("my_string in LOWERCASE: {0}", my_string.ToLower());
Console.WriteLine("my_string contains the letter y?: {0}", my_string.Contains("y"));
Console.WriteLine("New my_string: {0}", my_string.Replace("St", ""));
Console.WriteLine();
String example output
String Concatenation: connecting two string together called string concatenation which can be done via + operator or static String.Concat method. Such as below example:

string s1 = "Hey ";
string s2 = "World";
string s3 = s1 + s2;//result: "Hey World"
//or
string s4 = String.Concat(s1, s2);//result: "Hey World"

Escape Character:
Qualify how the character data should be printed to the output stream. Each escape characters begins with a backslash followed by a specific token:
  •  \' : insert single quote
  • \" : insert double quote
  • \\ : insert backslash
  • \a : Trigger system alert (beep)
  • \n : Insert new line
  • \r : Insert carriage return
  • \t : Inset horizontal tab
Console.WriteLine("Escape Characters Example:\t \"C:\\Program\\MyCSharpBlog\"\a ");
//Output: 
//Escape Characters Example:         "C:\Program\MyCSharpBlog\"
//and a system alert (beep)
    Verbatim Strings:
    When a string prefixed with @ symbol which disables the processing of a literal's Escape character and print out a string as is. Also preserve white spaces for strings that flow over multiple lines. In order to insert double quote into string using verbatim string you need to double " token

    Console.WriteLine(@"Escape Characters Example:       ""C:\Program\MyCSharpBlog""
    Also preserve white space
                                      more white space");

    Verbatim String example output
    Strings are Immutable, once you initial value, the character data cannot be changed. C# assignment operator will create a copy of string and the old one will eventually be garbage collected. Hence string class can be inefficient in some cases.In case you need to use many string manipulation and concatenation is better to use StringBuilder (next topic).

    System.Text.StringBuilder Type:
    By calling members of this type, you are directly modifying the object's internal character data which makes it more efficient. StringBuilder lives in System.Text, don't forget the use the "using System.Text;"
    StringBuilder is only able to initially hold a string of 16 characters or fewer by default however it will expand automatically if necessary. The default starting value can be changed via an additional constructor argument.

    Console.WriteLine("############# StringBuilder ##############");
    Console.WriteLine();
    // initial size of 512.
    StringBuilder string_bilder = new StringBuilder("**** .NET4 ****", 512);


    string_bilder.Append("\n");
    string_bilder.AppendLine("C#");
    string_bilder.AppendLine("VB");
    string_bilder.AppendLine("ASP.net");
    string_bilder.AppendLine("WPF");

    Console.WriteLine(string_bilder.ToString());
    string_bilder.Replace("VB", "Silverlight");

    Console.WriteLine(string_bilder.ToString());
    Console.WriteLine("string_builder has {0} chars.", string_bilder.Length);
    StringBuilder example output
    Data Type Conversions:
    •  Widening: an implicit upward cast that does not result in a loss of data. (e.g. store short to int)
    • Narrowing: opposite of widening, in that a larger value is stored within a smaller data type variable (e.g.store int to short) , in such a case explicit casting is needed, otherwise you will encounter compile time error.
    int int_num = 40000;
    short short_num = (short)int_num;
    Console.WriteLine("short_num = {0} ", short_num);
    //Output: short_num = -25536

    Checked keyword: with help of checked keyword CLI emits additional CIL instruction that test for overflow conditions. Runtime exception of System.OverflowException will receive if an overflow has occurred.
     
    int int_num = 40000;
    short short_num = 0;
    try
    {
        short_num = checked((short)int_num);
        Console.WriteLine("short_num = {0} ", short_num);
    }
    catch (OverflowException ex)
    {
        Console.WriteLine(ex.Message);
    }
    //Output: Arithmetic operation resulted in an overflow.

    Checked and Unchecked keyword is there to ensure data loss dose not escape undetected.
    You may do following setting to check the overflow project wise, however keep in mind to disable the setting for final build of your application since it have some effect on runtime performance.
    Set the flag via "project-properties-> Build -> Advanced...->Checked for arithmetic overflow/underflow"

    Set Checked flag Project wide
    Unchecked keyword: when you set the checked flag project wise and need to ignore the overflow and disable the throwing of an overflow exception you might use the unchecked keyword.

    System.Convert:
    also used to widen or narrow data. System.Convert provides a language-natural manner to convert between types (e.g. C# is different from VB)

    Implicitly Typed Local Variable: (var)
    The var keyword can be used in place of specifying specific data type (such as int, bool, etc) and results in strongly typed data. When you do so compiler based on initial value infer the underlying data type. Hence it must be assigned a initial value at the exact time of declaration (can not initialized by null). Implicit typing applies only to local variables in a method or property scope. You are not allowed to use the var keyword to define return values, parameters, or field data of a custom type. Good to know we can't define nullable implicit variables. implicit typing is helpful in LINQ technology which use of query expression that can yield dynamically created result sets based on the format of the query itself. Here is a good example how var can be helpful...

    int[] numbers_array = { 1, 2, 3, 4, 100, 200, 300, 600 };
    var implicit_var = from i in numbers_array where i > 100 select i;

    Console.Write("Values in implicit_var: ");
    foreach (var element in implicit_var)
    {
        Console.Write("{0} ", element);
    }
    Console.WriteLine();
    Console.WriteLine();

    Console.WriteLine("implicit_var is : {0}", implicit_var.GetType().Name);
    Console.WriteLine("implicit_var defined in: {0}", implicit_var.GetType().Namespace);

    Implicit typed example output
    C# Iteration:
    • for loop
    • foreach/in loop
    • while loop
    • do/while loop
    The if/else statement in C# operates only on Boolean expressions, not ad hoc values such as -1 or 0.

    Reference: Pro C# 2010 and the .NET 4 Platform by Andrew Troelsen.

    No comments:

    Post a Comment