C Sharp the Nuts and Bolts

  • Upload
    vscrni

  • View
    220

  • Download
    0

Embed Size (px)

Citation preview

  • 8/11/2019 C Sharp the Nuts and Bolts

    1/276

    243884994.doc 1 od 276

    C sharp The Nuts and Bolts

    Contents

    Authors

    Introduction

    1.Concepts Revisited

    2.Statements

    3.Enums

    4.Types

    5.Delegates and Events

    6.Conversions - Implicit and Explicit

    7.Operators

    8.Nested Classes

    http://vijaymukhi.com/documents/books/csadv/contents.htm
  • 8/11/2019 C Sharp the Nuts and Bolts

    2/276

    243884994.doc 2 od 276

    9.Miscellaneous

    10.Compiler Error Messages

    Authors

    Vijay Mukhi([email protected]) is one of the pioneers of the Indian Infotech Industry. For

    years, he has been the first to teach the emerging technologies in India thus ensuring that

    India always has people trained in technologies that the world requires. Vijay has written

    over 80 books on computers and programming over the last eight years on subjects ranging

    from C, C++ (The Odyssey Series) to Animation and Networking to Java to C#. His newly

    released book 'C#-The Basics' has covered many aspects of C# programming language in the

    most simplified form. Vijay abhors complexities and hence his books showcase the most

    difficult concepts explained through small programs, thereby giving a good understanding.

    Microsoft's .Net technologies is what Vijay is now focussing on and he aims at writing

    volumes on it.

    Sonal Mukhi([email protected]) is a freeance !ro"rammer havin" a #ides!read

    e$!osure to com!uter techni%ues and an"ua"es. &ona has done "round'reakin" #ork on

    various nternet echnoo"ies ike *ava+ ,ctive-+ er+ C/ and more. &he has co0authored a

    fe# 'ooks on com!uter !ro"rammin" too.

    ntroduction

    This is our second book on C# so we have assumed that you have read our first book, 'C# -The Basics'. It contains a lot more on the C# language that we could not cover in the first

    one.

    We have read a lot on what Microsoft and others have written, and wherever we liked the

    idea, we simply copied it. And because we have picked from so many places, there was just

    no way we could mention each and every of them. If you like an idea in this volume, please

    do the same. The objective is to spread the C# message!

    People often tend to compare C# with Java. It is with reason, and there's nothing wrong in

    doing so. All that we would like to say is that C# has everything of Java and more. But very

    soon, you could well have Java or some other language that betters C#'s act.

    Today, C# is king of the hill, but we don't know how long it will last. If and when the king is

    dethroned, we will be there paying our respects to the new king. With a new book, of course.

    We are basically teachers, and believe that a book is a simple extension of teaching. So in

    our books, we go step-by-step and systematically because that is the way one teaches in

    real-life.

    Requirements

    The software requirements to successfully run all the programs in this book are

    Operating System - Windows 2000

  • 8/11/2019 C Sharp the Nuts and Bolts

    3/276

  • 8/11/2019 C Sharp the Nuts and Bolts

    4/276

    243884994.doc 4 od 276

    the entry point of the program. It is the fountainhead of all knowledge. Incidentally, the C

    programming language also calls Main as its first function for all C-language programs.

    We can have as many as four different ways to declare Main in our program. They are as

    follows:

    static void Main() {...}static int Main() {...}static void Main(string[] a) {...}static int Main(string[] args) {...}

    The operating system calls Main and waits for it to return a value. This value denotes the

    success or failure of the program.

    Main can either return a number or result in no return value, that is, void. If it returns an

    int, by convention, a value of zero means success and any other value indicates an error. No

    international authority can standardize the error numbers, it largely depends on the

    programmer himself.

    Copy as a command takes two parameters; the source and destination files. Similarly, a C#

    program can also accept command line parameters at runtime. The executable a.exe can be

    entered as

    >a one two three

    a.csclass zzz{public static void Main(string[] a)

    {int i;for ( i!; i" a.#ength; i$$)%&ste'.onsole.rite#ine(a[i]);}}

    *utputonetwothree

    one, two, three are called command line parameters. The program accepts them in an array

    of strings. As the array is a parameter to the function, we are free to decide on its name.Every array has a member called Length, which tells us the size of the array. In our case, it

    is three. Thus, a[0] will contain the first word one and not the name of the program, a[1] will

    contain two and a[3] - three. Main now behaves like any other function. What we do next

    with the command line arguments depends entirely upon us.

    a.csclass zzz{public static void Main(string[] a){}

    public static int Main(){}

  • 8/11/2019 C Sharp the Nuts and Bolts

    5/276

    243884994.doc od 276

    }o'piler +rrora.cs(,-!)/ error %!!01/ 2rogra' 3a.e4e3 has 'ore than one entr& point defined/3zzz.Main(string[])3a.cs(5-06)/ error %!!01/ 2rogra' 3a.e4e3 has 'ore than one entr& point defined/ 3zzz.Main()3

    You can have one and only one function called Main in any C# program. Even though you

    can call it with different parameters, with the name changing, Main as a function must be

    given only once.

    a.csclass zzz{public static void Main(int i){}}

    o'piler arninga.cs(,-0)/ warning %!!7/ 3zzz.Main(int)3 has the wrong signature to be an entr& pointo'piler +rrorerror %8!!0/ 2rogra' 3a.e4e3 does not have an entr& point defined

    Here, the compiler first displays a warning signaling us that Main has not been created with

    the right parameters. The error, following the warning, proclaims that we have forgotten to

    create a function called Main. The signature includes the return type only in special cases

    as entry point.

    a.cs

    class zzz{public static long Main(){return !;}}o'piler arninga.cs(,-!)/ warning %!!7/ 3zzz.Main()3 has the wrong signature to be an entr& pointo'piler +rrorerror %8!!0/ 2rogra' 3a.e4e3 does not have an entr& point defined

    The signature refers to the parameters given to the function plus the return value. Main in

    the above program returns 'long', hence we see the error.

    a.csclass zzz{public void Main(){}}

    o'piler +rrorerror %8!!0/ 2rogra' 3a.e4e3 does not have an entr& point defined

  • 8/11/2019 C Sharp the Nuts and Bolts

    6/276

    243884994.doc 6 od 276

    The signature also includes modifiers like static etc. It just proves the importance of the

    function Main and the way it has been defined.

    a.csclass zzz {public static void Main()

    {}}class &&&{public static void Main(){}}o'piler +rrora.cs(-0)/ error %!!01/ 2rogra' 3a.e4e3 has 'ore than one entr& point defined/ 3zzz.Main()3a.cs(7-0)/ error %!!01/ 2rogra' 3a.e4e3 has 'ore than one entr& point defined/ 3&&&.Main()3

    The error proves the point that you cannot have two different classes, zzz and yyy,

    containing Main. Only one occurrence of Main is allowed. You always have only one chance

    of a lifetime. Ditto with Main.

    a.csclass zzz{private static void Main(){%&ste'.onsole.rite#ine(9hell9);}}

    *utputhell

    The access modifiers are not included within the signature for Main. Even though Main is

    made private, it is considered as an entry point function, hence hell gets displayed. This

    function is unique and works as a special case.

    a.cspublic static void Main() {%&ste'.onsole.rite#ine(9hell9);}

    class zzz{}

    o'piler +rrora.cs(0-08)/ error %0807/ +4pected class- delegate- enu'- interface- or struct

    You cannot create a function outside a class or a structure. This rule has to be strictly

    adhered to even for Main.

    a.cspublic class zzz

    {public static int Main(){

  • 8/11/2019 C Sharp the Nuts and Bolts

    7/276

    243884994.doc 7 od 276

    return;}}

    o'piler +rrora.cs(8-0)/ error %!05/ :n obect of a t&pe convertible to 3int3 is re

  • 8/11/2019 C Sharp the Nuts and Bolts

    8/276

    243884994.doc 8 od 276

    a.cs(7-0)/ error %!0!,/ =he na'e 3i3 does not e4ist in the class or na'espace 3zzz3

    A variable is visible from the position it is created to the first close bracket. As i has been

    created within the inner brackets, it is not available to external code thereafter. Hence the

    error.a.csclass zzz {public static void Main() {for ( int i!; i " 0!; i$$){}i 6!;}}

    o'piler +rrora.cs(5-0)/ error %!0!,/ =he na'e 3i3 does not e4ist in the class or na'espace 3zzz3

    The variable i has been created within the for statement; therefore it can be accessed only

    within the brackets pertaining to for. The scope of i is limited to the for {}.

    a.csclass zzz{void abc(){i 6;}public static void Main(){ }int i ;}

    The compiler does not read a .cs program in one iteration. If it did so, then the above

    program would have resulted in an error as the function abc refers to the variable i which

    has not been created for the moment. In the first round, the C# compiler scans the entire

    code. In another pass, it reads the code of abc. As the first pass had already brought i into

    existence, it does not generate any error and compiles successfully. We can use a variable of

    a class before it is declared/created provided the variable has been declared before the class

    ends.a.csclass zzz

    {void abc(){i 6;int i ;}public static void Main(){ }}

    o'piler +rrora.cs(8-0)/ error %!0!,/ =he na'e 3i3 does not e4ist in the class or na'espace 3zzz3

    What works for variables in a class does not apply to functions as well. Within abc, we, first,initialize i to 9 and on the next line we create it. The compiler is not aware of i's existence

  • 8/11/2019 C Sharp the Nuts and Bolts

    9/276

  • 8/11/2019 C Sharp the Nuts and Bolts

    10/276

    243884994.doc 1 od 276

    variable and value defined within zzz. i now plays two different roles with different scopes in

    the same class.a.csclass zzz{public static void Main()

    {int ( 0) ;%&ste'.onsole.rite#ine();}}

    *utput0

    The compiler gives no error as the variable j is being used on the same line of its creation. It

    does not precede it. Had it been like in the previous example, an error would have been

    generated. The compiler first reads the line, creates a variable called j, then initializes it to 1.

    The () brackets gain precedence.

    a.csclass zzz{public static void Main(){int 0 - i $$ ;%&ste'.onsole.rite#ine(i);}}

    *utput

    A comma works like a semi-colon. The compiler treats it as two different statements.

    Exceptions

    a.csclass zzz{public static void Main(){&&& a;

    anew &&&();tr&{a.abc();%&ste'.onsole.rite#ine(9?&e9);}catch{%&ste'.onsole.rite#ine(9@n +4ception9);}}}class &&&{

    public void abc(){

  • 8/11/2019 C Sharp the Nuts and Bolts

    11/276

    243884994.doc 11 od 276

    throw new %&ste'.+4ception();}}

    *utput@n +4ception

    When we call a function, we are not aware of the exceptions and the types of exceptions it

    will throw. One way to eradicate this uncertainty is to catch all the exceptions. You can do

    so by not specifying any Exception with catch. It is perfectly legal tender to unspecify the

    name of the Exception we are trying to catch in the catch.

    a.csclass zzz{public static void Main(){&&& a;

    anew &&&();tr&{a.abc();%&ste'.onsole.rite#ine(9?&e9);}catch{%&ste'.onsole.rite#ine(9@n +4ception9);}catch (%&ste'.+4ception e){%&ste'.onsole.rite#ine(9@n +4ception9);}

    }}class &&&{public void abc(){throw new %&ste'.+4ception();}}

    o'piler +rrora.cs(05-0)/ error %0!01/ =r& state'ent alread& has an e'pt& catch blocA

    The error message is self-explanatory. The C# compiler does not permit you to have a catchwith no Exceptions followed by a catch with an Exception. The reason being that the first

    catch is more generic and it will catch all the Exceptions. This leaves no exceptions for the

    second catch. Reverse the order of the catches and watch the error disappear.

    a.csclass zzz{public static void Main(){&&& a;anew &&&();

    tr&{a.abc();

  • 8/11/2019 C Sharp the Nuts and Bolts

    12/276

    243884994.doc 12 od 276

    %&ste'.onsole.rite#ine(9?&e9);}catch (444 e){%&ste'.onsole.rite#ine(9@n +4ception9 $ e.=o%tring());}}}class &&&{public void abc(){throw new 444();}}class 444 / %&ste'.+4ception{}

    *utput

    @n +4ception444/ :n e4ception of t&pe 444 was thrown. at &&&.abc() at zzz.Main()

    An exception is a class derived from System.Exception. It is child's play to create an

    exception. We can create hundreds of Exceptions, there is no certain limit to it. The reason

    behind introducing Exceptions was to simplify the job of identifying errors. Earlier if our

    function returned six different types of errors then the method would return six different

    numbers. Now, using exceptions it will throw 6 different objects. All these objects are derived

    from the System.Exception class.

    In the program above, xxx is derived from System.Exception and contains no code. Functionabc throws an object that looks like xxx hence the catch traps an xxx object while calling

    the function. The output is displayed using the ToString function of the object.

    a.csclass zzz{public static void Main(){&&& a;anew &&&();tr&{

    a.abc();%&ste'.onsole.rite#ine(9?&e9);}catch (%&ste'.+4ception e){%&ste'.onsole.rite#ine(9@n +4ception9 $ e.=o%tring());}catch (444 e){%&ste'.onsole.rite#ine(9@n +4ception9 $ e.=o%tring());}}}class &&&{public void abc()

  • 8/11/2019 C Sharp the Nuts and Bolts

    13/276

    243884994.doc 13 od 276

    {throw new 444();}}class 444 / %&ste'.+4ception{}

    o'piler +rrora.cs(05-7)/ error %!05!/ : previous catch clause alread& catches all e4ceptions of this or a supert&pe (3%&ste'.+4ception3)

    System.Exception catches all the exceptions. It is very similar to having a catch with no

    Exceptions. It is advisable to make it the last catch in the series of catches as if it is the

    first, it will catch all the exceptions leaving nothing for the other catches. The earlier

    explanation holds true in this case too.

    Exceptions are said to be a structured, type safe and a uniform way of error handling. All

    modern programming languages support exceptions.a.csclass zzz{public static void Main(){&&& a;anew &&&();tr&{a.abc();%&ste'.onsole.rite#ine(9?&e9);}catch (%&ste'.+4ception e){%&ste'.onsole.rite#ine(9@n +4ception9 $ e.=o%tring());}finall&{%&ste'.onsole.rite#ine(9@n finall&9);}}}class &&&{public void abc(){

    throw new %&ste'.+4ception();}}

    *utput@n +4ception%&ste'.+4ception/ :n e4ception of t&pe %&ste'.+4ception was thrown. at &&&.abc() at zzz.Main()@n finall&

    And if we comment out the throw statement.

    *utput?&e@n finall&

  • 8/11/2019 C Sharp the Nuts and Bolts

    14/276

    243884994.doc 14 od 276

    Once an exception is thrown, control passes to the catch statements. The statements in try

    following the function that causes an exception, are never executed. After executing the

    catch code, the next executable statement is the one following the try-catch block.

    Irrespective of an exception being thrown or not, the statements following the try catch

    blocks are executed. The question here is 'What if we want some code to be called

    irrespective of whether an exception occurred a not'. To do so, we simply place the code infinally. The code within this block unquestionably is executed. A finally will always be called

    at the end.

    a.csclass zzz{public static void Main(){int i 8B!;}}

    o'piler *utputa.cs(8-6)/ error %!!!/ Civision b& constant zero

    The C# compiler is very intelligent. It knows that a number cannot be divided by zero and

    thus stops us in our tracks with an error.

    a.csclass zzz {public static void Main(){int !;int i 8B;

    }}

    It is however not very smart and in the above case, an exception is generated at run time.

    a.csclass zzz{public static void Main(){tr&{int !;

    int i 8B;}catch ( %&ste'.+4ception e){%&ste'.onsole.rite#ine(9Di 9 $ e.=o%tring());}}}

    *utputDi %&ste'.Civide?&Eero+4ception/ :tte'pted to divide b& zero. at zzz.Main()

    All exceptions thrown at run time can be caught using try-catch. In this way, anyunforeseen application error can be caught at run time gracefully.

  • 8/11/2019 C Sharp the Nuts and Bolts

    15/276

  • 8/11/2019 C Sharp the Nuts and Bolts

    16/276

    243884994.doc 16 od 276

    In the program, abc does not throw any exception but pqr does. The catch that catches it is

    the inner catch and not the outer catch. Hence, the outer catch is not called. Conversely, the

    finally for both the trys is called, the order is from the inner to the outer resulting into

    seeing bye before last. Finally waits for the try-catch to complete its task.

    Namespaces

    C# programs are organized using namespaces which provide an organizational system for

    presenting programs. A source file is defined as a compilation unit. A C# program can

    consist of one or more compilation units. When we try and compile a C# program, all

    compilation units are compiled together and hence can depend on each other.

    a.cspublic na'espace via&{}

    o'piler +rrora.cs(0-7)/ error %0807/ +4pected class- delegate- enu'- interface- or struct

    A namespace is explicitly public and we are not allowed to specify any access modifiers to it.

    a.cspublic class zzz{public static void Main(string[] a){using %&ste';}}

    o'piler +rrora.cs(8-1)/ error %0!!,/ %&nta4 error- 3(3 e4pecteda.cs(8-0,)/ error %0!5/ ) e4pected

    The using directive can only be placed at the beginning of the program. It cannot be used

    anywhere else. The scope of using is the current source file and it does not influence any

    other programs included while compiling.

    a.cspublic class zzz{

    public static void Main(string[] a){}}na'espace n0{class &&&{}}na'espace n0{class &&{}}

  • 8/11/2019 C Sharp the Nuts and Bolts

    17/276

    243884994.doc 17 od 276

    Namespaces are open-ended, the net result here will be that the namespace n1 will contain

    both classes -- yy and yyy. However, we cannot change the name of the second class to yyy

    as we cannot have the same name in the same namespace.

    a.csusing z a0.a.&&&;using z0 a0.a;public class zzz{public static void Main(string[] a){z b;z0.&&& c;}}na'espace a0.a{class &&& {}

    }

    Using nested namespaces can make our names too large. We are provided with some help in

    the form of an alias in the using directive. In the program, we have created two aliases -- z

    and z1. Wherever we write a1.a2.yyy, the full name of the class yyy, it can now be replaced

    with z. z1 stands for only the namespace name and thus we have to specify the name of the

    class. An alias is conceptually very simple. Wherever C# sees a z, it will blindly replace it by

    a1.a2.yyy.

    a.csusing z a0.a.&&&;public class zzz{public static void Main(string[] a){}}na'espace a0.a{class &&& {}}class z{}

    o'piler +rrora.cs(0-1)/ error %!815/ Fa'espace 33 alread& contains an alias definition for 3z3

    You cannot have a class name and an alias with similar names as this will confuse the

    compiler. Hence the error.

    a.csna'espace a0.a{using z a0.a.&&&;class &&& {}}na'espace a,{class ddd / z

  • 8/11/2019 C Sharp the Nuts and Bolts

    18/276

    243884994.doc 18 od 276

    {}}

    o'piler +rrora.cs(7-0,)/ error %!5/ =he t&pe or na'espace na'e 3z3 could not be found (are &ou 'issing a

    using directive or an asse'bl& referenceG)

    The class zzz remains the same as before. An alias created in one namespace or compilation

    unit is simply not available to another. The scope of z is only limited to namespace a1.a2.

    a.csusing z a0.a.&&&;na'espace a0.a{class &&& {}}na'espace a,{

    class ddd / z{}}

    Here we do not get any namespace error as we have placed the alias in the global or default

    namespace. It is available to all namespaces in this source file only.

    a.csusing z a0.&&&;na'espace a,{class ddd / z{}}o'piler +rrora.cs(0-00)/ error %!5/ =he t&pe or na'espace na'e 3a03 could not be found (are &ou 'issing ausing directive or an asse'bl& referenceG)a.cs(0-00)/ error %!5/ =he t&pe or na'espace na'e 3a03 could not be found (are &ou 'issing ausing directive or an asse'bl& referenceG)

    C# checks the namespace alias and tries to resolve it to a sensible entity. If the compiler

    cannot resolve it, it gives an error. Here C# is not knowledgeable of a1.

    a.csusing z a.a,;na'espace a.a,{}na'espace a,{using z a;class ddd / z.&&&{}}

    o'piler +rrora.cs(7-08)/ error %!,/ =he t&pe or na'espace na'e 3&&&3 does not e4ist in the class orna'espace 3a3 (are &ou 'issing a using directive or an asse'bl& referenceG)

  • 8/11/2019 C Sharp the Nuts and Bolts

    19/276

    243884994.doc 19 od 276

    The namespace alias can be hidden by another namespace alias. Globally z is a2.a3 but

    within the namespace a3 it is temporarily given a value of a2. Thus the error reads a2.yyy

    and not a2.a3.yyy. If we comment the inner alias, the compiler evaluates z to be a2.a3.yyy.

    a.csna'espace a.a,{}na'espace a,{using z a;using z0 a.a,;using z z.a,;}

    o'piler +rrora.cs(7-0)/ error %!5/ =he t&pe or na'espace na'e 3z3 could not be found (are &ou 'issing ausing directive or an asse'bl& referenceG)

    The above error comes in as C# interprets only one using at a time. This means that C#

    turns a blind eye to the other using's. The order of usings is of no relevance. We cannot

    incorporate an alias within another. All of them have to be self contained with no

    dependencies.

    a.csusing a;using a,;class zzz{public static void Main()

    {aaa a;}}na'espace a{class aaa {}}na'espace a,{class aaa {}}

    o'piler +rrora.cs(1-0)/ error %!0!/ 3aaa3 is an a'biguous reference

    The reason we get an error is because in Main, aaa can either become a2.aaa or a3.aaa. As

    both namespaces a2 and a3 have a class aaa, both match and hence the error.

    Changing using a2 to using a3, will give us only warnings as duplicate usings are not

    flagged as an error. The class aaa now becomes a3.aaa and there is no ambiguity.

    a.csna'espace aa{na'espace bb

    {class cc{}}

  • 8/11/2019 C Sharp the Nuts and Bolts

    20/276

    243884994.doc 2 od 276

    }na'espace aa.bb{class cc{}}o'piler +rrora.cs(0!-1)/ error %!0!0/ =he na'espace 3aa.bb3 alread& contains a definition for 3cc3

    We cannot have a class cc in namespace aa.bb as it already exists within the namespace bb

    under namespace aa. The namespaces are additive, so it finally becomes aa.bb. The fully

    qualified name for the existing class cc is aa.bb.cc. Thus namespace aa.bb can be viewed as

    a namespace aa containing a namespace bb.

    Variables

    Variables are always stored in memory as they represent a memory location. They cannot be

    stored in your or my pockets. The name of a variable is always decided by consulting an

    astrologer. This is because you always need someone to take the flak for your programs not

    working, so why not blame it on a poor choice of variable names? Remember, in this book,

    we decide names of variables, in your life let your loved ones decide!

    Every human being has to have some properties associated with him or her. One of these

    could be, say, weight. In the same way every variable has to have a data type associated with

    it, that informs C# about the values that can be stored in it. C# is very finicky about what

    you store in it, similar to people who are very finicky about the clothes they wear. The C#

    compiler guarantees that the variable will never ever have a value other than what is

    permitted by its data type. Big brother is always watching over your shoulder!

    Variables in C# fall in two states, initially assigned and initially unassigned. An initially

    assigned variable has a defined value, an initially unassigned variable does not. Complex

    words but a simple explanation.

    If you have been counting, C# has so far created seven types of variables for us. These are:

    static, instance, array, parameter types like value, reference and output and finally local

    variables. Let us learn something more about each one of them.

    a.cspublic class zzz {public static int i0;

    int i;b&te [] i,;void abc(int i- ref int i8- out int i5){int i1 ;i50!;}public static void Main(){}}

    First, a quick recap. i1 is a static variable due to the keyword static. i2 is an instance

    variable as it is created outside a function and i3[0] is an array element if we initialize thearray member using new. Parameters by default are passed by value like i4. Variables like i5

  • 8/11/2019 C Sharp the Nuts and Bolts

    21/276

    243884994.doc 21 od 276

    and i6 are ref and out respectively due to the modifiers. Also, as i7 is created within a

    function, it is called a local variable.

    A static variable is born at the time the class is loaded and is alive and kicking as long as

    the program runs. A static variable is initially assigned which means that it gets the default

    values of its data type.

    All other variables created by themselves in a class are called instance variables. Aninstance variable comes to life only when an instance of that class is created using the

    keyword new. The instance variable dies when there are no more references to the object. In

    languages like C#, like in real life, we have no control over death. Thus, instance variables

    die whenever C# feels that it has no use for them. The programmer is powerless to kill an

    instance variable.

    An instance variable is initially assigned which means that it gets the default values of its

    data type. The above line was simple cut and paste from the above paragraph. The only

    change made was that the word instance was replaced by static. Good writers can waste

    many words writing gibberish. A structure is always created on the stack. Thus, an instance

    variable created in a structure, has the same life-time as the structure. If the structure isinitially assigned so are the instance variables and vice versa.

    Array members behave in the same way as instance members so we see no point in

    explaining the same concept using different words and consuming more paper and cutting

    more trees. We apologize but had to have the above explanation spread over at least three

    lines without repeating ourselves.

    A value parameter is assigned a value at the time of function invocation. The variable is alive

    at the open brace { and dies at the close brace }. A reference variable unlike a value variable

    does not create a new memory location. It simply stands for a reference to the original

    object. It represents the original memory location of the object in the function invocation.

    Within a structure, the keyword this is passed by reference. A reference variable has to be

    assigned a value on invocation unlike the out parameter. The out parameter is similar to the

    ref in many aspects. Both have the same value as the underlying variable. We cannot

    initialize an out variable at the time of invocation but must initialize it at the time of exit.

    Also, as it is initially unassigned, we cannot read its value in the function. The keyword 'this'

    in the constructor of a struct is an out parameter.

    A local variable is created at the open { and dies at the close }. A local variable is never

    initialized and thus has no default value.

    a.cspublic class zzz{public static void Main(){int i;%&ste'.onsole.rite#ine(i);}}

    o'piler +rrora.cs(5-5)/ error %!058/ Hse of unassigned local variable 3i3

    A local variable is initially unassigned.

  • 8/11/2019 C Sharp the Nuts and Bolts

    22/276

    243884994.doc 22 od 276

    a.cspublic class zzz{public static void Main(){i 0!;int i;}}

    o'piler +rrora.cs(8-0)/ error %!0!,/ =he na'e 3i3 does not e4ist in the class or na'espace 3zzz3

    We cannot refer to a variable before it is created and if we do so, the above error is reported.

    Had i been an instance variable and created even after Main, it would not have resulted in

    an error.

    a.cspublic class zzz{public static void Main(){i 0!;}static int i;}o'piler arninga.cs(1-0)/ warning %!056/ =he private field 3zzz.i3 is never used

    All that we get from C# is a benign warning saying that we are not using the variable i. From

    the compiler vocabulary, initializing a variable is not similar to using a variable. At times,

    the garbage collector responsible for the murder of variables may decide to terminate it

    before the close } as it is not being referred to. This is perfectly legal in C#. Thus a variable

    may die an earlier death, it is all at the mercy of the great C#.

    As a repetition, static, instance and array members all have default values. For a reference

    variable, the default value is null.

    a.cspublic class zzz{public static void Main()

    {%&ste'.onsole.rite#ine(9.9 $ i $ 9.9);}static &&& i;}class &&&{}o'piler arninga.cs(1-0)/ warning %!56/ Iield 3zzz.i3 is never assigned to- and will alwa&s have its defaultvalue null

    *utput..

  • 8/11/2019 C Sharp the Nuts and Bolts

    23/276

    243884994.doc 23 od 276

    i is a variable of a reference type. The warning very clearly informs us that C# has detected a

    variable i, which has not been initialized to any value hence it will be null. Null means no

    value and cannot be displayed. Null is not even a space and hence the two dots have nothing

    separating them.

    Arrays

    An array is also known as a data structure in formal computer science books. In our view, a

    rose by any other name is perceived to smell as sweet no matter what name you call it by. An

    array will normally contain more than one variable called the elements of the array. An

    array element is accessed using a number in square brackets known by a more difficult

    name -- a computed index. Unfortunately, all the members of an array must have the same

    data type called the array type. The value we supply to the keyword new in square brackets

    is the size of the array or as termed in the array world, a rank specifier.

    In Book 1, we have seen only single-dimensional arrays or arrays of rank one. In case of

    more than one index, we call it a multi-dimensional array. The array dimension isrepresented by a value, which must be larger than or equal to zero. This value is defined as

    length and must be positive. It does not have a compile time value but receives a value at

    run time.

    a.csclass zzz{public static void Main(){int [] a;a new int[];}}

    o'piler +rrora.cs(5-0)/ error %0875/ :rra& creation 'ust have arra& size or arra& initializer

    During the act of creating an array, the size must be specified.

    a.csclass zzz{public static void Main(){

    int [] a;a new int[!];}}

    It is valid or perfectly legal to give a size of 0. The array, however, has no practical value if

    you do so.

    a.csclass zzz {public static void Main(){int [] a;

    a new int[0!];a[00] 0!;

  • 8/11/2019 C Sharp the Nuts and Bolts

    24/276

    243884994.doc 24 od 276

    }}*utput+4ception occurred/ %&ste'.@nde4*ut*fJange+4ception/ :n e4ception of t&pe%&ste'.@nde4*ut*fJange+4ception was thrown. at zzz.Main()

    If you exceed the bounds of an array, you will not get any compile time error but

    unfortunately you land up to a run time error. C#, in other words, is extremely concerned

    about going beyond the scope of the array. The exception thrown can be caught by your

    program.

    Once an array has been created, its length cannot be altered any more. We are not allowed

    to resize the dimensions. Everything is fixed.

    a.csclass zzz

    {public static void Main(){int [] a;a new int[0!];a new int[0];}}

    The first array remains inaccessible in the program as array a has been redefined as one

    element array. Once an array has been created it cannot be resized later.

    All arrays are derived from System.Array, which is an abstract class.a.csclass zzz{public static void Main(){string [] a;a new string[0!];a[0] 6;}}

    o'piler +rrora.cs(1-7)/ error %!!6/ annot i'plicitl& convert t&pe 3int3 to 3string3

    The conversion rules applying to data types also apply to an array.

    a.csclass zzz{public static void Main(){int [] a new int[,] {!--7};int [] b new int[] {!--7};int [] c {!--7};

    }}

  • 8/11/2019 C Sharp the Nuts and Bolts

    25/276

    243884994.doc 2 od 276

    There are many ways to skin a cat. In the same way, we can initialize an array in different

    ways. The array a has been initialized the long way where we have specified the keyword new

    with the size of the array along with the initial values in {} braces. In the case of b, we've

    skipped the length and directly supplied three values. The length of this array becomes 3. In

    the third case, we have done away with the new altogether.

    a.csclass zzz{public static void Main(){int [] a new int[8] {!--7};}}

    o'piler +rrora.cs(8-)/ error %!017/ @ncorrectl& structured arra& initializer

    We cannot create a larger array and supply fewer values in the {} brackets. They have to bethe same. Not one more, not one less.

    a.csclass zzz{public static void Main(){int[-] b {{!- 0}- {- ,}- {- 8}- {5- 1}- {7- 6}};%&ste'.onsole.rite#ine(b.#ength);foreach ( int i in b)%&ste'.onsole.rite(i $ 9 9);}

    }*utput0!! 0 , 8 5 1 7 6

    We have created a two dimensional array having a length of five for the innermost rank and

    2 for the outermost rank. It is similar to writing 'b = new int[5,2]' and then initializing the

    individual members; b[0, 0]=0, b[0, 1]=1 etc. The member Length in System.Array, inherited

    by b displays 10 as the total number of members in the array are 5*2. The foreach construct

    then displays every member in the array.

    a.csclass zzz{public static void Main(){int ,;int[] b new int[];%&ste'.onsole.rite#ine(b.#ength);}}

    *utput,

  • 8/11/2019 C Sharp the Nuts and Bolts

    26/276

    243884994.doc 26 od 276

    Irrespective of what the documentation has to say, you are allowed to use a variable to

    initialize an array. We have used the variable j to create b.

    int [][,,][,] a, is a three-dimensional array consisting of two-dimensional arrays which in turn

    are of single-dimensional arrays each. The value stored in each element will be an integer.

    a.csclass zzz{public static void Main(){int b[];}}o'piler +rrora.cs(8-5)/ error %!58!/ %&nta4 error- bad arra& declarator. =o declare a 'anaged arra& the ranAspecifier precedes the variable3s identifiera.cs(8-1)/ error %088/ @nvalid e4pression ter' 3]3a.cs(8-7)/ error %0!!,/ %&nta4 error- 3]3 e4pected

    The array square brackets must come before the name of the variable and not after. These

    are issues of syntax and do not follow any coherent pattern. The above line would be a valid

    C syntax.

    a.csusing %&ste';public class zzz{public static void Main(string[] a){

    b&te[][] s new b&te[8][];%&ste'.onsole.rite#ine(s.#ength);for (int i !; i " s.#ength; i$$){s[i] new b&te[i$,];}for (int i !; i " s.#ength; i$$){onsole.rite#ine(9#ength of row {!} is {0}9- i- s[i].#ength);}}}

    *utput8#ength of row ! is ,#ength of row 0 is #ength of row is 8#ength of row , is 5#ength of row is 1

    A jagged array has a variable number of members. s is a jagged array with 5 members. Each

    of these 5 members can be made up of an array of any size. In the first for, we are initializing

    s[0], the first member, to an array of bytes which is 3 large. In the second iteration of the for,

    s[1] now points to an array of bytes having 4 members. Thus, in the second round,

    s[1].Length displays 4.

    a.cs

  • 8/11/2019 C Sharp the Nuts and Bolts

    27/276

    243884994.doc 27 od 276

    using %&ste';public class zzz{public static void Main(string[] a){int[][] n7 new int[][] { new int[] {-,-}- new int[] {8-5-1-7-6} };int[][] n6 new int[][] { new int[] {-,-}- new int[] {8-5-1-7} };}}

    And one more example for the road to ponder on. This shows the levels of complexities that

    you can delve in.

    a.csclass zzz{public static void Main(){int [] a {0-,};

    zzz b new zzz();b.abc(a);b.abc(new int[]{-8});%&ste'.onsole.rite#ine(a[0]);}public void abc( int [] z){%&ste'.onsole.rite#ine(z[0]);z[0] 0!!;}}

    *utput

    ,80!!

    You can give an array as a parameter to a function. This can be done in two ways, either by

    stating an array name explicitly or by creating an array at the time of creating the function.

    There is no way on earth the function can ever know or care on the method you have

    adopted. However, an array is passed by reference and any changes made through z will

    reflect the values in the original array.

    In the second case, even though the changes get incorporated, there is no way of accessing

    the array, as we never gave it a name. Change the function abc by adding the params

    keyword. This is as shown below.

    public void abc(para's int [] z)

    and the above program runs exactly the same as earlier. This proves that a params keyword

    is nothing but an array parameter.

    a.csclass zzz{public static void Main(){

    int [] a {0-,};zzz b new zzz();b.abc(a);

  • 8/11/2019 C Sharp the Nuts and Bolts

    28/276

    243884994.doc 28 od 276

    b.abc(a-a);}public void abc(int [] &- para's int [] z){%&ste'.onsole.rite#ine(z.#ength);}}

    *utput!

    There is, however, a major difference between an array and a params parameter. If the

    parameter is an array then no other data type can be provided other than an array. Even a

    single int has to be passed as an array. However, a params modifier is more flexible as we

    are allowed to give individual data types. These are converted into an array. A params

    parameter can also be null as in the first invocation of abc. We can either pass an array or

    as many individual ints we desire to the second parameter.

    a.csclass zzz{public static void Main(){int [] a {0-,};zzz b new zzz();b.abc(out a);%&ste'.onsole.rite#ine(a[]);}public void abc(out int [] z){z new int[,]{0--5};}}

    *utput5

    With an array, we can also use the modifiers of ref and out. The difference between them is

    that in the out modifier, we have to recreate an array within the function despite having

    initialized it earlier. An out modifiers demands new entities to be created inside the function.

    If the data type is an array, so be it, you must create it and if we do not initialize it, the value

    is automatically initialized to zero. Apart from this distinction, the behaviour followed is like

    a normal ref entity. Like any normal object, a variable needs to be initialized before using itbut in case of an out, if the array is not initialized, then it takes the default values of the

    data type.

    An array can be initialized to a null if need arises as a null may mean no value. This also

    means that someone somewhere gave it no value.

    a.csclass zzz{public static void Main(){

    int [] a new int[,]{0-};}}

  • 8/11/2019 C Sharp the Nuts and Bolts

    29/276

    243884994.doc 29 od 276

    o'piler +rrora.cs(8-)/ error %!017/ @ncorrectl& structured arra& initializer

    Whenever we initialize an array, the size of the array stated in the new and the values to be

    initialized must be the same in number. In the above case, we are creating an array of three

    ints and supplying values to initialize only two of them. We thought, wrongly so, that the

    last member a[2] would be initialized to zero. The compiler proved us wrong by giving us an

    error instead.

    a.csclass zzz{public static void Main(){int [] a new int[,];%&ste'.onsole.rite#ine(a[!] $ 9.9 $ a[0]);}

    }

    *utput!.!

    An array type is always initialized to the default value of its type. In the above case the

    default value is zero as the type of the array is an int.

    a.csclass zzz {public static void Main(){int i !;int [] a new int[,]{i$$-i$$-i$$};%&ste'.onsole.rite#ine(a[!] $ 9.9 $ a[0] $ 9.9 $ a[]);}}*utput!.0.

    No astonishing facts for a function! Same rules apply here too. No side effects at all. Each

    initialization is done independent of each other and starting from left to right.

    a.csclass zzz

    {public static void Main(){&&& a0 new &&&(0);&&& b0 new &&&(0!);&&& c0 new &&&(0!!);int [] a new int[,] ;tr&{a new int[,]{a0-b0-c0};}catch ( %&ste'.+4ception e){%&ste'.onsole.rite#ine(a[!] $ 9.9 $ a[0] $ 9.9 $ a[]);}%&ste'.onsole.rite#ine(a[!] $ 9.9 $ a[0] $ 9.9 $ a[]);

  • 8/11/2019 C Sharp the Nuts and Bolts

    30/276

    243884994.doc 3 od 276

    }}class &&&{public int i;public &&&(int ){i ;}public static i'plicit operator int ( &&& z){%&ste'.onsole.rite#ine(9op 9 $ z.i);if ( z.i 0!)throw new %&ste'.+4ception();return z.i;}}*utputop 0op 0!

    !.!.!!.!.!

    We create an array of ints and initialize them to objects that smell like yyy's. There is no

    problem in doing so as the operator int converts the yyy object into an int.

    For the object b1 whose instance variable i has a value 10, we throw an exception. Due to

    this, the compiler at run time undoes the initialization of array member a[0] to 1 and it falls

    back to the earlier default value of zero. This is the first task it performs on exceptions. The

    array members have to be initialized as the initialization statement is in a try block. If we fail

    to do so, we get an 'uninitialized variable error'. In this way, we fool the compiler into doing

    our bidding.

    The array members are, by default, initialized to zero before they get their new values. The

    array access element must not be less than zero or greater than the size of the array, or else

    an exception is thrown. An initialization statement of int [] a = new int[10][] creates an array

    of ten members and each of them in turn is considered to be an array. Each of the 10 arrays

    being reference types is initialized to a value null. We cannot, however, do the following.

    a.csclass zzz{public static void Main()

    {int [][] a new int[,][];}}

    o'piler +rrora.cs(8-8)/ error %!017/ @ncorrectl& structured arra& initializera.cs(8-5)/ error %0!!/ ; e4pecteda.cs(8-5)/ error %088/ @nvalid e4pression ter' 3]3

    Ha Ha Ha!!! We are overjoyed as we confused the compiler to no end. One error on our part

    and the compiler bought the entire cavalry out by giving us three errors instead. We are

    forbidden to initialize a sub array at the time of creation, hence the error. They are to be

    initialized later and individually, as follows.

    a.cs

  • 8/11/2019 C Sharp the Nuts and Bolts

    31/276

    243884994.doc 31 od 276

    class zzz{public static void Main(){int [][] a new int[,][];a[!] new int[0];a[0] new int[0!];%&ste'.onsole.rite#ine(a.#ength $ 9 9 $ a[!].#ength $ 9 9 $ a[0].#ength );}}

    *utput, 0 0!

    The size of the array a is 3 and it contains three members which are an array of ints. The

    first one, a[0] contains only one int and the second a[1] has 10 ints. Not permitting the

    initialization of sub arrays at the time of creation brings in flexibility as we can now initialize

    each of them to any size we wish rather having the same size. In life also, one size does not

    fit all ever.

    A rectangular array is an array of arrays where all the sub arrays have the same length.

    This is more efficient than a multi dimensional array. If we write new int[10][] and initialize

    the sub arrays to new int[5], we are creating one main array and 10 sub arrays. However, if

    we write int [,] a = new int[10,5] we are only creating one array in all and also it uses only

    one statement. Compare and contrast it with the above and choose the one you are most

    comfortable with. It is finally a personal decision.

    Parameter arraysWhen we use a params parameter in its normal form, the data type to be specified must be

    of a type that can be directly or implicitly converted to the parameter array type. A similar

    thing happens with a value parameter. In the expanded form, we do not use an array but

    pass the parameters individually, which then is converted into an actual array. It is the

    compiler's job to create an array of the same data type and width and then initialize the

    members with the values stated as parameters. Finally, it uses this array as the params

    parameter to the function.

    Thus, if we had a simple function abc (params object [] a) and we called the function abc as

    abc(1,2,"hell"), then an array would be created as new object[] { 1,2,"hell"}. If the function iscalled with no parameters, then the array becomes an empty array. An array is created after

    all.

    a.csclass zzz{public static void Main(){int [] a new int[!];}}

    There is nothing to feel sorry about when we create an empty array.

  • 8/11/2019 C Sharp the Nuts and Bolts

    32/276

    243884994.doc 32 od 276

    a.csclass zzz{public static void Main(){zzz a new zzz();int i 0!;a.abc(i);%&ste'.onsole.rite#ine(i);}public void abc(obect a){%&ste'.onsole.rite#ine(a);a 0!!;}}

    *utput0!0!

    When calling the function abc, if we do not specify ref or out, then there is no way in hell

    that the value of i can be changed within the function. In the above case, we have upgraded

    our value parameter, i, to an object using a method called boxing. In spite of it being a

    reference type, a, which is an instance of class object, will not reflect any changes made

    within the function abc in Main. If you do not believe us, cast i to an object explicitly and yet

    nothing changes.

    The ther dds and Ends

    a.cs

    class zzz{public static void Main(){int [] a new int[0!];a[0-] 0!;}}

    o'piler +rrora.cs(5-0)/ error %!!/ rong nu'ber of indices inside []- e4pected 303

    A one- or a single-dimensional array can only have one indice and not 2. The error tells us

    that the compiler checks whether we have given the right number of indices but it does not

    check whether we have exceeded the bounds of the array. All this is part and parcel of the

    array error handling enforced by the compiler. It is unfortunately very selective in the type of

    error handling and some common errors go undetected.a.csstruct zzz{public static void Main(){%&ste'.onsole.rite#ine(9hi9);}}

    *utputhi

  • 8/11/2019 C Sharp the Nuts and Bolts

    33/276

    243884994.doc 33 od 276

    There is no rule in the world that mandates the Main function to be placed only in a class.

    Here we placed it in a structure. Main is the last function in the world to complain.

    You cannot place functions anywhere else in your program. All the rules binding other

    functions apply to Main also.

    a.csclass zzz{public static void Main(){%&ste'.onsole.rite#ine(9hi in zzz9);}}class &&& / zzz{public new static void Main()

    {%&ste'.onsole.rite#ine(9hi in &&&9);}}

    o'piler +rrora.cs(,-!)/ error %!!01/ 2rogra' 3a.e4e3 has 'ore than one entr& point defined/ 3zzz.Main()3a.cs(0!-)/ error %!!01/ 2rogra' 3a.e4e3 has 'ore than one entr& point defined/ 3&&&.Main()3

    In the above program, we have two functions called Main. This results in an error. Hey, but

    wait a minute, they are in separate classes, so shouldn't it be acceptable? The compiler

    however does not think so. It does not like this specific function, Main being repeated twice

    in separate classes. We cannot use the modifiers virtual, new or override, as the function is

    static. Always follow the simple dictum, only one love, so only one function called Main!

    a.csclass zzz{public static void Main(){&&& a new &&&();a.aa 0!;a.abc(ref a.aa);}

    }class &&&{public int aa{get {return !;}set {}}public void abc( ref int b){}}

    o'piler +rrora.cs(1-00)/ error %!!5/ : propert& or inde4er 'a& not be passed as an out or ref para'eter

  • 8/11/2019 C Sharp the Nuts and Bolts

    34/276

    243884994.doc 34 od 276

    If it walks like a duck, quacks like a duck, it's a duck. A property looks and feels like a

    variable but it is actually a series of functions or to be technically correct, accessors. Only a

    storage or memory location can be passed as a ref or an out parameter. A property is not

    allocated any memory and thus cannot be used wherever a variable can be used. All the

    restrictions of static apply to static properties too. The get accessor must terminate either in

    a return or a throw statement. Control cannot flow off the accessor body at the end. A setaccessor is like a function that returns void and it has an implicit parameter value.

    a.csclass zzz{public static void Main(){&&& a new &&&();a.aa 0!;%&ste'.onsole.rite#ine(a.aa);}}

    class &&&{public int -A !;public int aa{get{%&ste'.onsole.rite#ine(9get 9 $ );if ( A !){aa aa $ 0; BB aa$$A 0;}return ;

    }set{ value;%&ste'.onsole.rite#ine(9set 9 $ );}}}

    The above program does not give any compiler error. We are allowed to change the property

    value, within a property. If you do so, the program goes into an indefinite loop. This is

    regardless of the fact that by using the value of variable we ensure that the statement aa++

    is executed only once.a.csclass zzz{public static void Main(){&&& a new &&&();a.aa 0!;%&ste'.onsole.rite#ine(a.aa);}}class &&&{public int -A !;public int aa{

  • 8/11/2019 C Sharp the Nuts and Bolts

    35/276

    243884994.doc 3 od 276

    get{%&ste'.onsole.rite#ine(9get0 9 $ );aa ;%&ste'.onsole.rite#ine(9get 9 $ );return ;}set{ value;%&ste'.onsole.rite#ine(9set 9 $ );}}}

    *utputset 0!get0 0!set get

    We all have been dumb many a times in life. One proof lies in the above program. Here in

    the get accessor of property aa, we are calling the set accessor by giving the statement aa =

    4. No indefinite loop but crazy answers!! The long and short story for that matter is, do not

    call the get or set accessor with a property directly.

    An indexer is similar to a property other than the fact that the indexers, accessors take or

    accept parameters. A property is identified by a name, an indexer by its signature.

    a.csclass zzz{public static void Main(){ }}class &&&{public static int this[int i]{get {return !;}set {}}}

    o'piler +rror

    a.cs(7-06)/ error %!0!5/ =he 'odifier 3static3 is not valid for this ite'

    Unlike a property, an indexer cannot be static. A property cannot be accessed like an array

    or by element access, similar to an indexer. A get and a set accessor share the same

    parameter list that the indexer has. A property has no such luck and no parameters at all

    but the set receives the implicit parameter value.

    In an interface, the only job of an indexer is to declare the signature. Interfaces are smart.

    They cannot carry code. All that they do is boss around. They decide the signatures of

    functions, indexers etc. so that other people who implement them, follow the rules built in

    them.

    a.cs

  • 8/11/2019 C Sharp the Nuts and Bolts

    36/276

    243884994.doc 36 od 276

    na'espace aaa{int i;}o'piler +rrora.cs(,-0)/ error %!005/ : na'espace does not directl& contain 'e'bers such as fields or'ethods

    The compiler is very particular about what you place where. We are not allowed to place

    methods and fields directly in a namespace or outside a namespace. Nothing stops us from

    placing them in a class. These are the regulations to be followed in the compiler world.

    a.csna'espace aaa{public class zzz{public static void Main()

    {aaa a;}}}

    o'piler +rrorsa.cs(1-0)/ error %!007/ 3aaa3 denotes a 3na'espace3 where a 3class3 was e4pected

    Wouldn't you be surprised if you see a tiger instead of a dog? Similarly, we surprised the

    compiler. It expected a class/type name and instead comes by the name of a namespace.

    The above error is a generic error. If we give the name of a property instead of a class, the

    error number will be the same, but the message would change. A single error to take care ofmultiple possibilities. The generic rule clearly states that a CS0118 error number is emitted

    whenever the compiler gets something that it does not expect.

    a.csna'espace aaa{na'espace bbb.ccc{}}o'piler +rrora.cs(,-00)/ error %!0,/ annot use

  • 8/11/2019 C Sharp the Nuts and Bolts

    37/276

    243884994.doc 37 od 276

    We all wanted to come in class but using always beat us to the draw. We have no choice but

    to start our code with the using clause. This is a rule imposed upon us by the top brass and

    obey, we must.

    a.csnew class zzz { }

    o'piler +rrorsa.cs(0-0)/ error %08,!/ Ke&word new not allowed on na'espace ele'ents

    You cannot use new on namespace elements like class or struct. This is because we create

    them in a global namespace.

    a.csusing aa %&ste';using aa %&ste';

    o'piler +rror

    a.cs(-1)/ error %08,1/ =he using alias 3aa3 appeared previousl& in this na'espace

    The compiler hates seeing two of anything even though they are the same and cause no

    trouble. Thus, two using's are out whether they are the same or different. We are not

    allowed to even change our mind.

    a.csclass zzz{public static void Main(){string s Lh

    i;%&ste'.onsole.rite#ine(s);}}

    *utputhi

    The @ sign lets you start a string with ". The single change is that you can press enter and

    move to the next line, ending the string there. The compiler doesnt show any errors.

    a.cs

    class zzz{int i {0};}

    o'piler +rrora.cs(,-6)/ error %!5/ an onl& use arra& initializer e4pressions to assign to arra& t&pes. =r&using a new e4pression instead.

    The array notation can only be used with the array data type. The {} brackets are to be used

    exclusively with arrays only.

    a.csclass zzz{

  • 8/11/2019 C Sharp the Nuts and Bolts

    38/276

    243884994.doc 38 od 276

    public int[] a { - ,- {}};}o'piler +rrora.cs(,-5)/ error %!5,/ :rra& initializers can onl& be used in a variable or field initializer. =r&using a new e4pression instead.

    We cannot use the {} brackets to initialize an array within an array. For that we have to usethe keyword new instead. The {} can only be used for a single dimensional array.

    a.cspublic class zzz{int a[];}

    o'piler +rrora.cs(,-5)/ error %!58!/ %&nta4 error- bad arra& declarator. =o declare a 'anaged arra& the ranAspecifier precedes the variable3s identifier

    There is lots that the C# language has copied from C and C++ and along the way, it has

    changed the syntax of a few in the language. The array brackets must come before the name

    of the variable and we are not allowed to state the size of the array within them either. All

    this worked very well in C/C++, C# in this case looks a lot like Java.

    a.csclass zzz{public static void Main(string a [] ){}}

    o'piler +rrora.cs(,-,)/ error %088/ :rra& t&pe specifier- []- 'ust appear before para'eter na'e

    Array brackets [] can only be in one place. This is before the name of the array, not after.

    God alone knows why?!

    a.csclass zzz{public static void Main(){

    int[] a {0--,};foreach (int in a){}}}

    o'piler +rrora.cs(5-0)/ error %!,!/ =&pe and identifier are both re

  • 8/11/2019 C Sharp the Nuts and Bolts

    39/276

    243884994.doc 39 od 276

    Statements

    C# provides us with a countless number of statements. Let us now understand each one of

    them in detail.

    a.cspublic class zzz{public static void Main(){bool i false;if ( i)int !;}}

    o'piler +rrorsa.cs(1-0)/ error %0!,/ +'bedded state'ent cannot be a declaration or labeled state'ent

    It is not mandatory for the if statement to have the {} if we want to limit its scope to only one

    line. However, we cannot have a variable declaration as the only line following it. This is

    because if the condition results to false, the variable will never be created.

    The value of the variable i can only be determined at run time and thus C# flags an error.

    The line following the if condition, int j = 40; is called an embedded statement.

    Every C# statement has an end-point. The end-point is intuitively the end of the statement.If a statement can be executed, we call it a reachable statement else it is unreachable.

    Unreachable statements for some reason flag a warning and not an error. To figure out

    whether a statement is reachable or not, C# does flow analysis.

    a.cspublic class zzz{public static void Main(){int i ,!;const int ,!;if ( i ,)

    %&ste'.onsole.rite#ine(9hi9);if ( ,)%&ste'.onsole.rite#ine(9hi9);}}

    o'piler arninga.cs(0!-0)/ warning %!05/ Hnreachable code detected

    Two identical if statements. One produces unreachable code whereas the second does not.

    In the case of variable j, the compiler sees it as a const and therefore knows that its value

    will never change. The if will always end in false, therefore, a warning.

  • 8/11/2019 C Sharp the Nuts and Bolts

    40/276

    243884994.doc 4 od 276

    In the case of the first if, even though the value of variable i is 30 and C# knows that it

    results in false, it still believes that an act of God can change the value of variable i.

    Consequently, no error but a mere warning is generated

    As for the value of a const variable, even God possesses no privilege to change it, hence the

    compiler pops up a warning. The above rule is part of what goes under the moniker of flowanalysis. An end point should not be reached for a switch and a return statement.

    The if statement falls under the set of selection statement. It executes statements depending

    upon the value of a controlling expression.

    if (4) if (&) I(); else N();if (4) {

    if (&) {I();

    }else {

    N();

    }}

    This block of if statements is copied straight from the documentation to denote an idea. The

    above two ifs are the same. What we want to highlight here is that the brackets are optional;

    the visual look and feel can get misleading at times.

    Switch Statement

    a.cspublic class zzz{public static void Main(){zzz a new zzz();a.abc(0);a.abc(0!);}void abc(int i){switch (i){case !/%&ste'.onsole.rite#ine(9zero9);breaA;

    case 0/%&ste'.onsole.rite#ine(9one9);breaA;default/%&ste'.onsole.rite#ine(9end9);breaA;}}}*utputoneend

  • 8/11/2019 C Sharp the Nuts and Bolts

    41/276

    243884994.doc 41 od 276

    A switch statement is a substitute to multiple ifs as both work in the same fashion. It is a

    matter of style in deciding on the use of them. We use the time of day to decide which

    statement to use when and where. In other words, alike if, the switch also brings intelligence

    to our programs.

    The switch statement checks the value of the variable i against the values given with thecase statement. If any one value matches, all the statements within the case upto the break

    statement are executed. If none of the case statements match, the default statement is

    executed. Remember it is not mandatory to have a default statement with a break. The value

    of the variable in question decides on the code to be executed.

    a.cspublic class zzz{public static void Main(){}void abc(int i){switch (i){case !/%&ste'.onsole.rite#ine(9zero9);case 0/%&ste'.onsole.rite#ine(9one9);breaA;}}}o'piler +rror

    a.cs(7-0)/ error %!05,/ ontrol cannot fall through fro' one case label (3case !/3) to another

    The case statement has its own set of complex rules. The first one says that every case must

    end with a break statement; thereupon preventing it from encroaching into the next case.

    Don't we have railing to prevent us from falling over our balcony? Thus, there is no natural

    way invented to execute code within two case statements at the same time. Most people

    consider it to be an unnecessary restriction C# has placed on the usage of the case

    statement. Like everything in life, there is a workaround. But we will elaborate on that later.

    a.cspublic class zzz{

    public static void Main(){zzz z new zzz();z.abc(!);}void abc(int i){switch (i){case !/%&ste'.onsole.rite#ine(9second9);goto case 0;case 0/

    %&ste'.onsole.rite#ine(9first9);breaA;}

  • 8/11/2019 C Sharp the Nuts and Bolts

    42/276

    243884994.doc 42 od 276

    }}

    *utput

    secondfirst

    We explained that one case could not fall through another case but if it is imperative then

    you can use the goto statement. This statement accepts a case statement as a parameter

    and then simply jumps to it. Thus, after executing the code of one case, we can jump to

    another case and execute its code.

    a.cspublic class zzz{public static void Main()

    {zzz z new zzz();z.abc(!);}void abc(int i){switch (i){case !/%&ste'.onsole.rite#ine(9second9);goto case 0;%&ste'.onsole.rite#ine(9hi9);case 0/%&ste'.onsole.rite#ine(9first9);

    breaA;}}}

    o'piler arninga.cs(08-0)/ warning %!05/ Hnreachable code detected*utputsecondfirst

    Here we have confused the compiler to no end and we advise you not to write such code. At

    first, the compiler informs you that no lines of code after a goto will ever be called and thus

    generates an unreachable code warning.

    But then the control seeps to the case statement directed by goto and forgets that it was

    falling through a case statement from another. We are not trying to belittle the compiler but

    can it not please remember goto statements that we write and stop looking stupid in front of

    our eyes.

    a.cspublic class zzz{

    public static void Main(){zzz z new zzz();

  • 8/11/2019 C Sharp the Nuts and Bolts

    43/276

    243884994.doc 43 od 276

    z.abc(!);z.abc(,);z.abc(0);}void abc(int i){switch (i){case !/%&ste'.onsole.rite#ine(9zero9);goto case ,;case 0/%&ste'.onsole.rite#ine(9one9);goto default;case ,/%&ste'.onsole.rite#ine(9two9);breaA;default/%&ste'.onsole.rite#ine(9last9);breaA;

    }}}

    *utputzerotwotwoonelast

    To prevent a fall through, every case has to end either with a goto or a break. With a break

    statement, no other code gets called but with a goto, the code to be executed depends

    entirely on the case it jumps to. The above code is the ideal way to write code. However

    a.cspublic class zzz{public static void Main(){}void abc(int i){switch (i){case !/while ( true) ;case 0/return ;case ,/throw new %&ste'.+4ception();}}}

    The documentation very clearly states that the end point of the case statement must not be

    reached. Thus, any lines of code that prevent the last line of the case being executed is legal

    tender. A while (true) goes on forever, This make sure that you do not leave the while forever

    and thus the endpoint of the case never gets reached. Though it does not make any sense atall as i being zero will enter the while and never leave the case.

  • 8/11/2019 C Sharp the Nuts and Bolts

    44/276

    243884994.doc 44 od 276

    A return is more logical at this point as it can exit the function altogether and not just the

    case. It may be what you had in mind, however. A throw statement also breaks the case, the

    try catch is not mandatory here. Just because the compiler does not complain with a

    warning or an error it does not mean that you are home scott free.

    a.cspublic class zzz{public static void Main(){}void abc(int i){switch (i){case !/%&ste'.onsole.rite#ine(9zero9);breaA;

    case !/%&ste'.onsole.rite#ine(9one9);breaA;}}}

    o'piler +rrora.cs(0,-5)/ error %!08/ =he label 3case !/3 alread& occurs in this switch state'ent

    Somebody somewhere did some research and found out that people fell asleep while writing

    code. When they woke up, they rewrote the same code again. Thus, we had two copies of the

    same case in the program. C# peeks into human mind and is aware that you'd fall asleep atthe wheel.

    Thus, it checks whether you are writing the same code all over again. If it catches you in the

    act, you will see an error like the one above. It makes no logical sense having two case

    statements with the same value. If the value of i happens to be zero then there is confusion

    as in which case should C# execute. The first, the second, or both, or, even better, none.

    Decisions, decisions, they are so difficult to make, so the C# compiler drops by an error.

    a.cspublic class zzz{

    int 0!;public static void Main(){}void abc(int i){switch (i){case /breaA;case > /%&ste'.onsole.rite#ine(9zero9);breaA;

    }}}

  • 8/11/2019 C Sharp the Nuts and Bolts

    45/276

    243884994.doc 4 od 276

    o'piler +rrora.cs(00-5)/ error %!08!/ : constant value is e4pecteda.cs(0,-5)/ error %!!6/ annot i'plicitl& convert t&pe 3bool3 to 3int3

    Here we want to convince you that an if statement in our humble/esteem opinion is better

    than a switch statement. In a case statement, we have to check the variable with a constantvalue. We are not permitted to use a variable or a logical condition. They have to be constant

    predefined values only. This limits our flexibility in writing complex conditions thereby

    preventing us from writing more abstract more intelligent code.

    a.cspublic class zzz{public static void Main(){zzz z new zzz();z.abc(1);

    z.abc(1!);}void abc(int i){switch (i > 7){case > 8/%&ste'.onsole.rite#ine(9first9);breaA;case " 8/%&ste'.onsole.rite#ine(9second9);breaA;}}

    }

    *utputfirstsecond

    We could not for the life of us figure out, why the above program works. So we added the

    following lines at the end of the second case statement ergo producing an error.

    case ! > 8/%&ste'.onsole.rite#ine(9third9);breaA;

    and we got the following error

    o'piler +rrora.cs(06-5)/ error %!08/ =he label 3case 0/3 alread& occurs in this switch state'ent

    z.abc(7) initializes i to 7, hence the switch condition becomes false. The case may show

    logical operations but finally has either 1 or 0 standing for true or false. As the switch

    results in false, the first case is executed where case has a value of 0. In the second case,

    z.abc(70), the switch is true and thus the second case that evaluates to true gets called.

    In one of the earlier examples, we demonstrated that a duplicate case value was notadmissible. The error delivers the same message. In the above case, the compiler should

  • 8/11/2019 C Sharp the Nuts and Bolts

    46/276

    243884994.doc 46 od 276

    take up the Hitlerian attitude and erase all our code; to punish us for writing such

    gibberish.

    a.cspublic class zzz{

    public static void Main(){zzz z new zzz();&&& a new &&&();z.abc(a);}void abc(&&& i){switch (i){case !/%&ste'.onsole.rite#ine(9second9);breaA;

    case 0/%&ste'.onsole.rite#ine(9first9);breaA;}}}class &&&{}

    o'piler +rrora.cs(00-6)/ error %!080/ : value of an integral t&pe e4pected

    The C# compiler informs us that a switch statement can only take certain integral types. Tobe more specific, it can take an sbyte, byte, short, ushort, int, uint, long, ulong, char, string,

    or an enum-type. C# realizes that the switch has received a yyy object and since it cannot

    convert a yyy into the above integral types, it reports an error.

    a.cspublic class zzz{public static void Main(){zzz z new zzz();&&& a new &&&();z.abc(a);

    }void abc(&&& i){switch (i){case !/%&ste'.onsole.rite#ine(9second9);breaA;case 0/%&ste'.onsole.rite#ine(9first9);breaA;}}

    }class &&&{

  • 8/11/2019 C Sharp the Nuts and Bolts

    47/276

    243884994.doc 47 od 276

    public static i'plicit operator int ( &&& a){%&ste'.onsole.rite#ine(9operator9);return 0;} }

    *utputoperatorfirst

    The only way to eliminate the error is by overloading an int operator with class yyy. This will

    convert the yyy object into an int. As the function returns the resultant int as 1, the second

    case will be called. In a real life scenario, the return value depends upon some instance

    variable. Thus each time the switch statement will call the int operator to convert the yyy

    object into an int and then call the case statements depending on the resultant value.

    a.cspublic class zzz

    {public static void Main(){zzz z new zzz();&&& a new &&&();z.abc(a);}void abc(&&& i){switch (i){case !/%&ste'.onsole.rite#ine(9second9);breaA;

    case 0/%&ste'.onsole.rite#ine(9first9);breaA;}}}class &&&{public static i'plicit operator int ( &&& a){%&ste'.onsole.rite#ine(9operator9);return 0;}

    public static i'plicit operator b&te ( &&& a){%&ste'.onsole.rite#ine(9operator9);return 0;}}

    o'piler +rrora.cs(00-6)/ error %!080/ : value of an integral t&pe e4pected

    We really got off the wrong side of our bed today. We therefore added two operators, one that

    converts a yyy to an int and the other that converts a yyy to a byte. As the case has no

    preferences of a byte over a int, it gets confused and does not know which operator to call.

    Since both are equally probable, it flags an error. The switch expression decides on the

    governing type of the statement.

  • 8/11/2019 C Sharp the Nuts and Bolts

    48/276

    243884994.doc 48 od 276

    There are many more rules to switch that sensibly state that there can be no two defaults in

    a switch. The end-point, that is, the end of the switch must never be reachable or else it will

    result in a compile time error.

    a.cspublic class zzz{public static void Main(){zzz z new zzz();z.abc();z.abc(,);}void abc(int i){switch (i){case !/%&ste'.onsole.rite#ine(9first9);

    breaA;case ,/case /%&ste'.onsole.rite#ine(9second9);breaA;}}}

    *utputsecondsecond

    You can have many case statements bunched up together. There will be no errors if you doso. In the above switch, for the values 2 and 3, the same code is executed. Thus multiple

    labels are permitted in the switch. case 2: can be replaced by a default: and it would still

    result in the same answer. Though it is not a good programming style as removing the case

    2: would not change the answer and default means none of the above. The order of the case

    statements is irrelevant to the final answer so changing the order doesn't change anything.

    For that matter, the default came first for all that C# cares.

    The governing type of a switch can also be a string. The case statement values are however

    case sensitive. We can also use null as we are talking real objects here.

    Within a case statement we can use declaration statements i.e. create variables etc.

    a.cspublic class zzz{public static void Main(){zzz a new zzz();a.abc(!);}void abc(int i){switch (i)

    {case !/int 1;

  • 8/11/2019 C Sharp the Nuts and Bolts

    49/276

    243884994.doc 49 od 276

    %&ste'.onsole.rite#ine();breaA;}}}

    *utput1

    a.cspublic class zzz{public static void Main(){zzz a new zzz();a.abc(!);}void abc(int i){switch (i){int 1;case !/int A 1;breaA;case 0/%&ste'.onsole.rite#ine(A);breaA;}}}o'piler +rror

    a.cs(0-0)/ error %08,/ =he Ae&word case or default 'ust precede code in switch blocA

    For some reason, we are not allowed to create variables in the switch statement. Had we

    been allowed, then the variable would have scope in the entire switch. As we are allowed to

    create them only in a case, their scope is restricted to that case only. In the above program,

    remove the line int j = 7 and relish the error as seen below.

    o'piler +rrora.cs(05-5)/ error %!058/ Hse of unassigned local variable 3A3

    Empty

    A lot of life goes by without doing anything. As shown in one of the earlier examples, the

    while loop did absolutely nothing. Whenever a statement does nothing we call it an empty

    statement. Perfectly valid in C#. Execution of an empty statement simply transfers control to

    the statement's end point.

    a.cspublic class zzz{public static void Main(){}void abc(int i){goto aa;

  • 8/11/2019 C Sharp the Nuts and Bolts

    50/276

    243884994.doc od 276

    aa/}}

    o'piler +rrora.cs(0!-0)/ error %088/ @nvalid e4pression ter' 3}3

    a.cs(00-0)/ error %0!!/ ; e4pected

    We normally create labels at the end of a function so that all code can jump to the end if

    they so choose to. Here we have created a label aa on the last line of function abc. We get an

    error as C# demands at least one statement following the label.

    C# demands a statement so we have no choice but to give it an empty statement. The best

    way to cut short an argument is by doing what C# wants and give it a statement, albeit, an

    empty one, one that does nothing.

    a.cspublic class zzz {

    public static void Main(){}void abc(int i){goto aa;aa/ ;}}

    Just by placing a semicolon, we bring a big smile on the C# virtual face. ;)

    !oopsIn all, we have four iterative statements, the for, foreach, while and the last kid on the block,

    the do while.

    a.cspublic class zzz {public static void Main() {int i 0;do{%&ste'.onsole.rite(i $ 9 9);i$$;

    } while ( i " ,);}}*utput0 ,

    Earlier we learnt about the differences between the for and the while and the scientific

    reasons behind choosing one of them. Now we add a twist and introduce the do while. This

    is identical to the while. There is just one and only one difference between them. Minor but

    could be life-threatening at times. In a while, the condition is evaluated at the beginning of

    the loop whereas in the case of the do while it is at the end.

    a.cs

  • 8/11/2019 C Sharp the Nuts and Bolts

    51/276

    243884994.doc 1 od 276

    public class zzz {public static void Main() {int i 0;do{%&ste'.onsole.rite(i $ 9 9);i$$;} while ( i " !);i 0;while ( i " ! ) {%&ste'.onsole.rite(i $ 9...9);i$$;}}}*utput0

    In the do statement, the loop condition is checked at the end of the first iteration. Thus, the

    loop is executed at least once. In the above case, the condition i

  • 8/11/2019 C Sharp the Nuts and Bolts

    52/276

    243884994.doc 2 od 276

    a.cspublic class zzz{public static void Main(){int [] a new int[,]{0--,};foreach ( int i in a){%&ste'.onsole.rite(i $ 9 9);i 0!;zzz.abc(ref i);%&ste'.onsole.rite#ine(i);}}public static void abc(ref int ){%&ste'.onsole.rite(9abc 9 $ $ 9 9); 0!!;}}

    o'piler +rrora.cs(6-0)/ error %05!/ annot assign to 3i3 because it is readOonl&a.cs(0!-0,)/ error %05!8/ annot pass 3i3 as a ref or out argu'ent because it is readOonl&

    We are not allowed to change the iteration variable nor pass it as a ref or out parameter. We

    are doing both in the above program, hence the error.

    "ump Statements

    Jump statements transfer control to another part of our program. This transfer takes place

    come hell, hath or fury. In other words, the transfer is unconditional. We have exactly fiveconditional statements namely break, continue, goto, return and throw. The statements that

    a jump takes you to, is called the target of the jump.

    The break statement was touched upon in the switch statement where it exits out of the

    case. It works in a similar fashion for a while, for, foreach and do while. It simply exits out of

    the looping construct it is befitted in.

    a.cspublic class zzz{public static void Main()

    {breaA;}}

    o'piler +rrora.cs(8-0)/ error %!0,6/ Fo enclosing loop out of which to breaA or continue

    You cannot have a break statement by itself. It has to be placed within a case or a loop

    construct.

    a.cspublic class zzz {public static void Main() {int i 0- 0;

  • 8/11/2019 C Sharp the Nuts and Bolts

    53/276

    243884994.doc 3 od 276

    for ( i 0; i" 0! ; i$$) {if ( i ,)breaA;for ( 0; " 0!; $$){%&ste'.onsole.rite#ine(i $ 9.9 $ );if ( 0)breaA;}}%&ste'.onsole.rite#ine(i $ 9 9 $ );}}*utput0.0.0, 0

    The number of breaks introduced in the program must be equal to the loops statements. As

    all of us are very particular about money and will never forget who we lent it to, similarly C#is very finicky about breaks and hates it hanging around in the program code.

    The inner break makes sure that the inner for executes only once and not 10 times. It ends

    the loop each time the value of j reaches 1. The outer break lets us prematurely exit the

    outer for loop when the value of i is 3. As we love pairing up people, C# pairs up breaks with

    loops.

    a.cspublic class zzz{public static void Main()

    {int i 0- 0;for ( i 0; i" 0! ; i$$){if ( i ,)breaA;for ( 0; " 0!; $$){%&ste'.onsole.rite#ine(i $ 9.9 $ );if ( 0)goto aa ;}}aa/

    %&ste'.onsole.rite#ine(i $ 9 9 $ );}}

    *utput0.00 0

    There is no known way to quit out of nested breaks in this version of C#. You may have to

    wait till the next version and even then, no guarantees. The only alternative here is a goto

    statement; this we have shown in the above program. These days the goto statement has

    fallen in disrepute. No programmer worth his/her salt will admit in public that they have

    ever used the goto statement. Most respectable programming schools will refuse to teach it.

    Your programming mother will wash your mouth with soap if she finds out that you havebeen reading all about goto.

  • 8/11/2019 C Sharp the Nuts and Bolts

    54/276

    243884994.doc 4 od 276

    a.cspublic class zzz {public static void Main() {int i 0;for ( i 0; i" 0! ; i$$)

    {tr&{%&ste'.onsole.rite#ine(90 tr&9);

    tr&{%&ste'.onsole.rite#ine(9 tr&9);breaA;}finall&{%&ste'.onsole.rite#ine(9 finall&9);}

    }

    finall&{%&ste'.onsole.rite#ine(90 finall&9);}}%&ste'.onsole.rite#ine(i);}}

    *utput0 tr& tr& finall&

    0 finall&0

    The for loop starts and enters the first try, Here it comes across another try and then when

    least expected encounters a break. It would love to get out of the for statement but it stops to

    think for a while. The try statement has a finally clause. Hence before it exits the try, it

    executes the code in the finally. Now it remembers that there is one more try statement in

    the outstanding. This try also has a finally clause. Once the code in finally gets executed, C#

    exits from the for loop.

    Thus, if the break is nested among 20 finally clauses, all of them will first get executed and

    only then will the break perform its task. Replace the break with a goto aa: statement andthe above explanation will still hold true.

    a.cspublic class zzz{public static void Main(){int i 0;for ( i 0; i" 0! ; i$$){goto aa;}

    {aa/%&ste'.onsole.rite#ine(i);

  • 8/11/2019 C Sharp the Nuts and Bolts

    55/276

    243884994.doc od 276

    }}}

    o'piler +rrora.cs(7-0)/ error %!086/ Fo such label 3aa3 within the scope of the goto state'ent

    o'piler arninga.cs(00-0)/ warning %!05/ =his label has not been referenced

    You can never transfer control from one block to another block. The goto will allow you to

    leave a block but never let you enter another block. This results in the error shown above.

    The warning like every warning is at times best ignored.

    a.cspublic class zzz{public static void Main(){goto aa;{aa/;}}}

    o'piler +rrora.cs(8-0)/ error %!086/ Fo such label 3aa3 within the scope of the goto state'ento'piler arninga.cs(1-0)/ warning %!05/ Hnreachable code detecteda.cs(1-0)/ warning %!05/ =his label has not been referenced

    The compiler is very picky about you not entering a block. For those who came in late, a

    block is nothing but valid C# code in open and close brackets { }. Remember, come heaven or

    earth, you cannot enter a block. Add the above to one more mysteries in life that has no

    rational answer.

    a.cspublic class zzz{public static void Main(){for ( int i 0; i" 0! ; i$$)

    {tr&{}finall&{breaA;return ;}}}}

    o'piler +rrora.cs(0-0)/ error %!081/ ontrol cannot leave the bod& of a finall& clause

  • 8/11/2019 C Sharp the Nuts and Bolts

    56/276

    243884994.doc 6 od 276

    o'piler arninga.cs(0,-0)/ warning %!05/ Hnreachable code detectedo'piler +rrora.cs(0,-0)/ error %!081/ ontrol cannot leave the bod& of a finall& clause

    You cannot quit out of a finally block with a break or return statement. If you have a short-lived memory, we will repeat and tell you that the finally clause of a try is always called. You

    cannot leave a finally abruptly. All code in finally must be executed.

    We also heed to the warning that no code after a break ever is executed. In other words, the

    end point of a break will never be reached. If it does so, some people tell us that it signals

    the end of the world.

    a.cspublic class zzz{public static void Main()

    {for ( int i 0; i" ,; i$$){%&ste'.onsole.rite#ine(99 $ i);continue;%&ste'.onsole.rite#ine(9:9 $ i);}}}*utput0,

    The continue statement stops executing the balance statements and restarts a new iteration

    of the loop. It can be used in a while, do, foreach and obviously the for. The rules applied to

    break, like having a trillion of them, hold true here also. You can try the earlier programs of

    try and finally with continue in place of break.

    Similar to break, you cannot place continue in a finally block. A break says bye-bye to a loop

    whereas a continue restarts from the first line of the for loop. Continue is used when for

    some unknown reason, the programmer doesn't want to quit the loop but wants to skip the

    remaining code in the loop.

    It is then assumed that the code does not exist from the continue keyword to the end pointof the loop and the control moves to the beginning of the loop. Identical to a break, if you

    ever write any code after continue, C# will not execute it for a million years. After that if the

    sun is yet left standing, it will then execute your code. Most of what has been repeated

    earlier also applies to the return keyword.

    A goto abides by all rules of break and continue.a.cspublic class zzz{public static void Main(){int aa 0!;goto aa ;

  • 8/11/2019 C Sharp the Nuts and Bolts

    57/276

    243884994.doc 7 od 276

    aa/ ;}}

    C# stores the name of a label and the name of a variable in different sections of the

    program. As they belong to different namespaces, the above program does not generate any

    errors. Had C# stored the name of a function and name of a variable in a differentnamespaces, we could use the same name for both of them too.

    A good programming language design looks at different namespaces it requires and the

    contents within them. The teeming millions like us then abide by their decision and

    pontificate on its merits and demerits. We however are powerless to change any of their

    decisions. The idea here is that you understand a little in English and then apply that

    knowledge to a large number of C# statements.

    The checked and unchecked statements are similar to the corresponding operators except

    that these statements act on blocks. The lock statement applies to Threads.

    The ther dds and Ends

    a.csclass zzz{public static void Main(){aa/ ;aa/ ;}}o'piler +rrorsa.cs(1-0)/ error %!0!/ =he label 3aa3 is a duplicate

    Nothing, read my lips, Nothing can ever be a duplicate. Not even a label.

    a.csclass zzz {public static void Main(){goto case 8 ;}}

    o'piler +rrorsa.cs(8-0)/ error %!08,/ : goto case is onl& valid inside a switch state'ent

    A goto case statement only fits in a case statement. It cannot be used outside a case.

    a.csclass &&&{}class zzz{

    public static void Main(){la/

  • 8/11/2019 C Sharp the Nuts and Bolts

    58/276

    243884994.doc 8 od 276

    ;{la/;goto la;}}}

    o'piler +rrora.cs(0,-0)/ error %!087/ =he label 3la3 shadows another label b& the sa'e na'e in a containedscope

    Like variables, we cannot have two labels with the same name shadowing each other. If we

    use common sense then the goto would jump to the inner label. What makes sense to us is

    not what makes sense to the compiler. If we remove the goto statement, then the error too

    disappears.

    a.csclass zzz {public static void Main(){if ( true) ;}}o'piler arninga.cs(8-0)/ warning %!5/ 2ossible 'istaAen null state'ent

    The compiler does not like nothingness. A semi colon by itself stands for a valid statement

    but at the same time is an empty statement. If we use a semi colon only where a statement

    is due, the compiler gently prods us with a warning.

    a.csclass zzz{public static void Main(){int i 5;switch(i){}}}

    o'piler arninga.cs(7-0)/ warning %08/ +'pt& switch blocA

    m!ty vesses make the most noise. he com!ier does not understand anythin" em!ty

    incudin" a s#itch statement. ea$+ it is ony a #arnin" and can 'e i"nored

    Chapter 3

    Enums

    An enum is at the same level as a class, struct and interface. It performs a similar job of

    creating a new data type.

  • 8/11/2019 C Sharp the Nuts and Bolts

    59/276