Você está na página 1de 41

Concepts Revisited - C# Nuts and Bolt - Beta2

Chapter 1

Concepts Revisited
Entry Point
The first function to be called in any C# program is Main. Obviously someone at Microsoft tossed a coin and as it fell 'heads', they chose Main. Had it been 'tails', one wonders what the first function would have been called. As everything starts from Main, it is also called 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 static static static void Main() {...} int Main() {...} void Main(string[] a) {...} 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.cs class zzz { public static void Main(string[] a) { int i; for ( i=0; i< a.Length; i++) System.Console.WriteLine(a[i]); }
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (1 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

} Output one two three

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.cs class zzz { public static void Main(string[] a) { } public static int Main() { } } Compiler Error a.cs(3,20): error CS0017: Program 'a.exe' has more than one entry point defined: 'zzz.Main(string[])' a.cs(6,19): error CS0017: Program 'a.exe' has more than one entry point defined: 'zzz.Main()'

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.cs class zzz { public static void Main(int i) { } } Compiler Warning a.cs(3,21): warning CS0028: 'zzz.Main(int)' has the wrong signature to be an entry point Compiler Error error CS5001: Program 'a.exe' does not have an entry 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.
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (2 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs class zzz { public static long Main() { return 0; } } Compiler Warning a.cs(3,20): warning CS0028: 'zzz.Main()' has the wrong signature to be an entry point Compiler Error error CS5001: Program 'a.exe' does not have an entry 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.cs class zzz { public void Main() { } } Compiler Error error CS5001: Program 'a.exe' does not have an entry point defined

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.cs class zzz { public static void Main() { } } class yyy { public static void Main() { } } Compiler Error a.cs(2,21): error CS0017: Program 'a.exe' has more than one entry point defined: 'zzz.Main()' a.cs(8,21): error CS0017: Program 'a.exe' has more than one entry point defined: 'yyy.Main()'

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (3 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

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.cs class zzz { private static void Main() { System.Console.WriteLine("hell"); } } Output hell

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.cs public static void Main() { System.Console.WriteLine("hell"); } class zzz { } Compiler Error a.cs(1,15): error CS1518: Expected class, delegate, enum, 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.cs public class zzz { public static int Main() { return; } } Compiler Error a.cs(5,1): error CS0126: An object of a type convertible to 'int' is required

In this example, the function Main has to return an int and we are not returning any value with the keyword return. The compiler tries to convert a nothing into an int and hence the error. This is a generic error that occurs whenever the compiler tries to convert a data type into another and is not successful.
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (4 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs class zzz { public static int Main() {} } Compiler Error a.cs(3,19): error CS0161: 'zzz.Main()': not all code paths return a value

The compiler's error messages need the services of an editor. The function Main should return an int, but we forgot to do so. This results in an error. Thus whenever an entity should return a value, we should return such a data type or be prepared for an error.

Scope
Scope, as a concept, defines the region within which a user-defined entity is visible and can be referred to.
a.cs public class zzz { public static void Main() { int i; zzz i; }} Compiler Error a.cs(6,5): error CS0128: A local variable named 'i' is already defined in this scope

Twins are always a problem. We cannot have any two entities of the same name as the compiler will get confused on whether we are referring to the i which is an int or a zzz. Thus never have duplicate names even though at times they are allowed.
a.cs class zzz { public static void Main() { { int i = 8; } i = 90; }} Compiler Error a.cs(8,1): error CS0103: The name 'i' does not exist in the class or namespace 'zzz'

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (5 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

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.cs class zzz { public static void Main() { for ( int i=0; i <= 10; i++) { } i = 90; } } Compiler Error a.cs(6,1): error CS0103: The name 'i' does not exist in the class or namespace 'zzz'

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.cs class zzz { void abc() { i = 9; } public static void Main() {} int i = 4; }

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.cs class zzz { void abc() { i = 9; int i = 4; } public static void Main() {} }
Compiler Error
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (6 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs(5,1): error CS0103: The name 'i' does not exist in the class or namespace 'zzz'

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 while parsing the first line hence it stops and shows an error. Some people are born smart, well, our compiler is not one of them.
a.cs class zzz { void abc() { i = 9; int i = 4; } public static void Main() { } int i = 7; } Compiler Error a.cs(6,5): error CS0136: A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'parent or current' scope to denote something else

i as a variable is created in class zzz and is visible to all members in the class. Within the function abc, we have created another local variable but with the same name as i. If we are now to refer to i, then are we referring to the local i or the parent i? The local i in abc hides or prevents any access to the parent i. This turns out to be unacceptable to C# and hence it reports an error.
a.cs class zzz { public static void Main() { zzz a = new zzz(); a.abc(); a.pqr(); } int i = 100; void abc() { int i = 10; System.Console.WriteLine(i); } void pqr() { System.Console.WriteLine(i);

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (7 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

i = 1; } } Output 10 100

The program does not generate any compilation error. In function abc, we are allowed to create a variable named i, similar to the variable i in class zzz. The local variable in abc hides the parent variable in its function. Initializing i in abc to 10 hence does not change the value of i in zzz. Also, as there is no variable named i defined in pqr, i will refer to the variable and value defined within zzz. i now plays two different roles with different scopes in the same class. a.cs class zzz { public static void Main() { int j = ( j = 1) ; System.Console.WriteLine(j); } }
Output 1

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.cs class zzz { public static void Main() { int j = 1 , i = ++j ; System.Console.WriteLine(i); } } Output 2

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

Exceptions
a.cs

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (8 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

class zzz { public static void Main() { yyy a; a=new yyy(); try { a.abc(); System.Console.WriteLine("Bye"); } catch { System.Console.WriteLine("In Exception"); } } } class yyy { public void abc() { throw new System.Exception(); } } Output In Exception

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.cs class zzz { public static void Main() { yyy a; a=new yyy(); try { a.abc(); System.Console.WriteLine("Bye"); } catch { System.Console.WriteLine("In Exception"); } catch (System.Exception e) {
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (9 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

System.Console.WriteLine("In Exception"); } } } class yyy { public void abc() { throw new System.Exception(); } } Compiler Error a.cs(16,1): error CS1017: Try statement already has an empty catch block

The error message is self-explanatory. The C# compiler does not permit you to have a catch with 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.cs class zzz { public static void Main() { yyy a; a=new yyy(); try { a.abc(); System.Console.WriteLine("Bye"); } catch (xxx e) { System.Console.WriteLine("In Exception" + e.ToString()); } } } class yyy { public void abc() { throw new xxx(); } } class xxx : System.Exception { } Output

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (10 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

In Exceptionxxx: An exception of type xxx was thrown. at yyy.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. Function abc 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.cs class zzz { public static void Main() { yyy a; a=new yyy(); try { a.abc(); System.Console.WriteLine("Bye"); } catch (System.Exception e) { System.Console.WriteLine("In Exception" + e.ToString()); } catch (xxx e) { System.Console.WriteLine("In Exception" + e.ToString()); } } } class yyy { public void abc() { throw new xxx(); } } class xxx : System.Exception { } Compiler Error a.cs(16,8): error CS0160: A previous catch clause already catches all exceptions of this or a super type

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (11 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

('System.Exception')

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.cs class zzz { public static void Main() { yyy a; a=new yyy(); try { a.abc(); System.Console.WriteLine("Bye"); } catch (System.Exception e) { System.Console.WriteLine("In Exception" + e.ToString()); } finally { System.Console.WriteLine("In finally"); } } } class yyy { public void abc() { throw new System.Exception(); } }
Output In ExceptionSystem.Exception: An exception of type System.Exception was thrown. at yyy.abc() at zzz.Main() In finally

And if we comment out the throw statement.


Output Bye In finally

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (12 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

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 in finally. The code within this block unquestionably is executed. A finally will always be called at the end.
a.cs class zzz { public static void Main() { int i = 5/0; } } Compiler Output a.cs(5,9): error CS0020: Division by 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.cs class zzz { public static void Main() { int j = 0; int i = 5/j; } }

It is however not very smart and in the above case, an exception is generated at run time.
a.cs class zzz { public static void Main() { try { int j = 0; int i = 5/j; } catch ( System.Exception e) { System.Console.WriteLine("Hi " + e.ToString()); } } }
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (13 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

Output Hi System.DivideByZeroException: Attempted to divide by zero. at zzz.Main()

All exceptions thrown at run time can be caught using try-catch. In this way, any unforeseen application error can be caught at run time gracefully.
a.cs class zzz { public static void Main() { yyy a; a=new yyy(); try { a.abc(); try { a.pqr(); } catch (System.Exception e) { System.Console.WriteLine("In inner try" + e.ToString()); } finally { System.Console.WriteLine("In inner finally"); } System.Console.WriteLine("Bye"); } catch (System.Exception e) { System.Console.WriteLine("In Exception" + e.ToString()); } finally { System.Console.WriteLine("In finally" ); } } } class yyy { public void abc() { //throw new System.Exception(); } public void pqr() { throw new System.Exception(); } }
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (14 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

Output In inner trySystem.Exception: Exception of type System.Exception was thrown. at yyy.pqr() at zzz.Main() In inner finally Bye In finally

Interesting !!! Basically, you are allowed to have as many try-catch blocks in your code as your heart's desire. Every time you execute a function, that function may throw an exception. So you can place the function call in a try-catch block. Moreover, within a catch block, you can have another trycatch which should be considered only when there is a function call in the catch. 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.cs public namespace vijay { } Compiler Error a.cs(1,8): error CS1518: Expected class, delegate, enum, interface, or struct

A namespace is explicitly public and we are not allowed to specify any access modifiers to it.
a.cs public class zzz { public static void Main(string[] a) { using System; } } Compiler Error a.cs(5,7): error CS1003: Syntax error, '(' expected

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (15 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs(5,13): error CS1026: ) expected

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.cs public class zzz { public static void Main(string[] a) { } } namespace n1 { class yyy { } } namespace n1 { class yy { } }

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.cs using z = a1.a2.yyy; using z1 = a1.a2; public class zzz { public static void Main(string[] a) { z b; z1.yyy c; } } namespace a1.a2 { class yyy {} }

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
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (16 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

alias is conceptually very simple. Wherever C# sees a z, it will blindly replace it by a1.a2.yyy.
a.cs using z = a1.a2.yyy; public class zzz { public static void Main(string[] a) { } } namespace a1.a2 { class yyy {} } class z { } Compiler Error a.cs(1,7): error CS0576: Namespace '' already contains an alias definition for 'z'

You cannot have a class name and an alias with similar names as this will confuse the compiler. Hence the error.
a.cs namespace a1.a2 { using z = a1.a2.yyy; class yyy {} } namespace a3 { class ddd : z { } } Compiler Error a.cs(8,13): error CS0246: The type or namespace name 'z' could not be found (are you missing a using directive or an assembly reference?)

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.cs using z = a1.a2.yyy; namespace a1.a2 { class yyy {} }

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (17 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

namespace a3 { 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.cs using z = a1.yyy; namespace a3 { class ddd : z { } } Compiler Error a.cs(1,11): error CS0246: The type or namespace name 'a1' could not be found (are you missing a using directive or an assembly reference?) a.cs(1,11): error CS0246: The type or namespace name 'a1' could not be found (are you missing a using directive or an assembly reference?)

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.cs using z = a2.a3; namespace a2.a3 { } namespace a3 { using z = a2; class ddd : z.yyy { } } Compiler Error a.cs(8,15): error CS0234: The type or namespace name 'yyy' does not exist in the class or namespace 'a2' (are you missing a using directive or an assembly reference?)

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.cs namespace a2.a3

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (18 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

{ } namespace a3 { using z = a2; using z1 = a2.a3; using z2 = z.a3; } Compiler Error a.cs(8,12): error CS0246: The type or namespace name 'z' could not be found (are you missing a using directive or an assembly reference?)

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.cs using a2; using a3; class zzz { public static void Main() { aaa a; } } namespace a2 { class aaa {} } namespace a3 { class aaa {} } Compiler Error a.cs(7,1): error CS0104: 'aaa' is an ambiguous 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.cs namespace aa { namespace bb { class cc{}

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (19 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

} } namespace aa.bb { class cc{} } Compiler Error a.cs(10,7): error CS0101: The namespace 'aa.bb' already contains a definition for 'cc'

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.cs public class zzz { public static int i1; int i2; byte [] i3; void abc(int i4, ref int i5, out int i6) { int i7 ; i6=10; } public static void Main()
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (20 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

{ } }

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 the array member using new. Parameters by default are passed by value like i4. Variables like i5 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. An instance 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 is initially 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.cs public class zzz { public static void Main()
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (21 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

{ int i; System.Console.WriteLine(i); } } Compiler Error a.cs(6,26): error CS0165: Use of unassigned local variable 'i'

A local variable is initially unassigned.


a.cs public class zzz { public static void Main() { i = 10; int i; } } Compiler Error a.cs(5,1): error CS0103: The name 'i' does not exist in the class or namespace 'zzz'

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.cs public class zzz { public static void Main() { i = 10; } static int i; } Compiler Warning a.cs(7,12): warning CS0169: The private field 'zzz.i' 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.

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (22 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs public class zzz { public static void Main() { System.Console.WriteLine("." + i + "."); } static yyy i; } class yyy { } Compiler Warning a.cs(7,12): warning CS0649: Field 'zzz.i' is never assigned to, and will always have its default value null Output ..

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 is represented 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.cs class zzz { public static void Main() { int [] a; a = new int[]; } }

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (23 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

Compiler Error a.cs(6,14): error CS1586: Array creation must have array size or array initializer

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


a.cs class zzz { public static void Main() { int [] a; a = new int[0]; } }

It is valid or perfectly legal to give a size of 0. The array, however, has no practical value if you do so.
a.cs class zzz { public static void Main() { int [] a; a = new int[10]; a[11] = 10; } } Output Exception occurred: System.IndexOutOfRangeException: An exception of type System. IndexOutOfRangeException 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.cs class zzz { public static void Main() { int [] a; a = new int[10]; a = new int[1]; } }
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (24 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

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.cs class zzz { public static void Main() { string [] a; a = new string[10]; a[1] = 9; } } Compiler Error a.cs(7,8): error CS0029: Cannot implicitly convert type 'int' to 'string'

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


a.cs class zzz { public static void Main() { int [] a = new int[3] {0,4,8}; int [] b = new int[] {0,4,8}; int [] c = {0,4,8}; } }

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.cs class zzz { public static void Main() { int [] a = new int[5] {0,4,8}; } } Compiler Error a.cs(5,24): error CS0178: Incorrectly structured array initializer
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (25 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

We cannot create a larger array and supply fewer values in the {} brackets. They have to be the same. Not one more, not one less.
a.cs class zzz { public static void Main() { int[,] b = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}}; System.Console.WriteLine(b.Length); foreach ( int i in b) System.Console.Write(i + " "); } } Output 10 0123456789

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.cs class zzz { public static void Main() { int j = 3; int[] b = new int[j]; System.Console.WriteLine(b.Length); } } Output 3

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.cs class zzz { public static void Main()
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (26 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

{ int b[]; } } Compiler Error a.cs(5,6): error CS0650: Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's identifier a.cs(5,7): error CS1525: Invalid expression term ']' a.cs(5,8): error CS1003: Syntax error, ']' expected

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.cs using System; public class zzz { public static void Main(string[] a) { byte[][] s = new byte[5][]; System.Console.WriteLine(s.Length); for (int i = 0; i < s.Length; i++) { s[i] = new byte[i+3]; } for (int i = 0; i < s.Length; i++) { Console.WriteLine("Length of row {0} is {1}", i, s[i].Length); } } } Output 5 Length of Length of Length of Length of Length of

row row row row row

0 1 2 3 4

is is is is is

3 4 5 6 7

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 using System;

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (27 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

public class zzz { public static void Main(string[] a) { int[][] n8 = new int[2][] { new int[] {2,3,}, new int[] {5,6,7,8,9} }; int[][] n9 = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8} }; } }

And one more example for the road to ponder on. This shows the levels of complexities that you can delve in.
a.cs class zzz { public static void Main() { int [] a = {1,3}; zzz b = new zzz(); b.abc(a); b.abc(new int[]{4,5}); System.Console.WriteLine(a[1]); } public void abc( int [] z) { System.Console.WriteLine(z[1]); z[1] = 100; } } Output 3 5 100

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(params int [] z)

and the above program runs exactly the same as earlier. This proves that a params keyword is nothing but an array parameter.

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (28 of 41)2/21/2010 7:37:57 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs class zzz { public static void Main() { int [] a = {1,3}; zzz b = new zzz(); b.abc(a); b.abc(a,a); } public void abc(int [] y, params int [] z) { System.Console.WriteLine(z.Length); } } Output 0 2

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.cs class zzz { public static void Main() { int [] a = {1,3}; zzz b = new zzz(); b.abc(out a); System.Console.WriteLine(a[2]); } public void abc(out int [] z) { z = new int[3]{1,4,6}; } } Output 6

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
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (29 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

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 it but 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.cs class zzz { public static void Main() { int [] a = new int[3]{1,2}; } } Compiler Error a.cs(5,22): error CS0178: Incorrectly structured array 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.cs class zzz { public static void Main() { int [] a = new int[3]; System.Console.WriteLine(a[0] + "." + a[1]); } } Output 0.0

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.cs class zzz { public static void Main() { int i = 0; int [] a = new int[3]{i++,i++,i++}; System.Console.WriteLine(a[0] + "." + a[1] + "." + a[2]); } }
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (30 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

Output 0.1.2

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.cs class zzz { public static void Main() { yyy a1 = new yyy(1); yyy b1 = new yyy(10); yyy c1 = new yyy(100); int [] a = new int[3] ; try { a = new int[3]{a1,b1,c1}; } catch ( System.Exception e) { System.Console.WriteLine(a[0] + "." + a[1] + "." + a[2]); } System.Console.WriteLine(a[0] + "." + a[1] + "." + a[2]); } } class yyy { public int i; public yyy(int j) { i = j; } public static implicit operator int ( yyy z) { System.Console.WriteLine("op " + z.i); if ( z.i == 10) throw new System.Exception(); return z.i; } } Output op 1 op 10 0.0.0 0.0.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.

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (31 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

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.cs class zzz { public static void Main() { int [][] a = new int[3][2]; } } Compiler Error a.cs(5,25): error CS0178: Incorrectly structured array initializer a.cs(5,26): error CS1002: ; expected a.cs(5,26): error CS1525: Invalid expression term ']'

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 class zzz { public static void Main() { int [][] a = new int[3][]; a[0] = new int[1]; a[1] = new int[10]; System.Console.WriteLine(a.Length + " " + a[0].Length + " " + a[1].Length ); } } Output 3 1 10

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.

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (32 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

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 arrays
When 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 is called with no parameters, then the array becomes an empty array. An array is created after all.
a.cs class zzz { public static void Main() { int [] a = new int[0]; } }

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


a.cs class zzz { public static void Main() { zzz a = new zzz(); int i = 10; a.abc(i); System.Console.WriteLine(i); } public void abc(object a) { System.Console.WriteLine(a); a = 100; } }
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (33 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

Output 10 10

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 Other Odds and Ends


a.cs class zzz { public static void Main() { int [] a = new int[10]; a[1,2] = 10; } } Compiler Error a.cs(6,1): error CS0022: Wrong number of indices inside [], expected '1'

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.cs struct zzz { public static void Main() { System.Console.WriteLine("hi"); } }
Output hi

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.

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (34 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs class zzz { public static void Main() { System.Console.WriteLine("hi in zzz"); } } class yyy : zzz { public new static void Main() { System.Console.WriteLine("hi in yyy"); } } Compiler Error a.cs(3,20): error CS0017: Program 'a.exe' has more than one entry point defined: 'zzz.Main()' a.cs(10,24): error CS0017: Program 'a.exe' has more than one entry point defined: 'yyy.Main()'

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.cs class zzz { public static void Main() { yyy a = new yyy(); a.aa = 10; a.abc(ref a.aa); } } class yyy { public int aa { get {return 0;} set {} } public void abc( ref int b) { } }

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (35 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

Compiler Error a.cs(7,11): error CS0206: A property or indexer may not be passed as an out or ref parameter

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 set accessor is like a function that returns void and it has an implicit parameter value.
a.cs class zzz { public static void Main() { yyy a = new yyy(); a.aa = 10; System.Console.WriteLine(a.aa); } } class yyy { public int j,k = 0; public int aa { get { System.Console.WriteLine("get " + j); if ( k == 0) { aa = aa + 1; // aa++ k = 1; } return j; } set { j = value; System.Console.WriteLine("set " + j); } } }

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.cs class zzz
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (36 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

{ public static void Main() { yyy a = new yyy(); a.aa = 10; System.Console.WriteLine(a.aa); } } class yyy { public int j,k = 0; public int aa { get { System.Console.WriteLine("get1 " + j); aa = 4; System.Console.WriteLine("get2 " + j); return j; } set { j = value; System.Console.WriteLine("set " + j ); } } } Output set 10 get1 10 set 4 get2 4 4

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.cs class zzz { public static void Main() {} } class yyy {

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (37 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

public static int this[int i] { get {return 0;} set {} } } Compiler Error a.cs(8,19): error CS0106: The modifier 'static' is not valid for this item

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 namespace aaa { int i; } Compiler Error a.cs(3,1): error CS0116: A namespace does not directly contain members such as fields or methods

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.cs namespace aaa { public class zzz { public static void Main() { aaa a; } } } Compiler Errors a.cs(7,1): error CS0118: 'aaa' denotes a 'namespace' where a 'class' was expected

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
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (38 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

number will be the same, but the message would change. A single error to take care of multiple possibilities. The generic rule clearly states that a CS0118 error number is emitted whenever the compiler gets something that it does not expect.
a.cs namespace aaa { namespace bbb.ccc { } } Compiler Error a.cs(3,11): error CS0134: Cannot use qualified namespace names in nested namespace declarations

We can have namespaces within namespace with nary a nod from the compiler. What we cannot have is a qualified namespace within another namespace. Why? Ask the designers of the language.
a.cs class zzz { } using System; Compiler Error a.cs(4,1): error CS1529: A using clause must precede all other namespace elements

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.cs new class zzz { } Compiler Errors a.cs(1,1): error CS1530: Keyword new not allowed on namespace elements

You cannot use new on namespace elements like class or struct. This is because we create them in a global namespace.
a.cs using aa = System; using aa = System; Compiler Error a.cs(2,7): error CS1537: The using alias 'aa' appeared previously in this namespace

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.

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (39 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs class zzz { public static void Main() { string s = @h i; System.Console.WriteLine(s); } } Output h i

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 = {1}; } Compiler Error a.cs(3,9): error CS0622: Can only use array initializer expressions to assign to array types. Try using a new expression instead.

The array notation can only be used with the array data type. The {} brackets are to be used exclusively with arrays only.
a.cs class zzz { public int[] a = { 2, 3, {4}}; } Compiler Error a.cs(3,26): error CS0623: Array initializers can only be used in a variable or field initializer. Try using a new expression instead.

We cannot use the {} brackets to initialize an array within an array. For that we have to use the keyword new instead. The {} can only be used for a single dimensional array.
a.cs public class zzz { int a[2]; } Compiler Error
http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (40 of 41)2/21/2010 7:37:58 PM

Concepts Revisited - C# Nuts and Bolt - Beta2

a.cs(3,6): error CS0650: Syntax error, bad array declarator. To declare a managed array the rank specifier precedes the variable's 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.cs class zzz { public static void Main(string a [] ) { } } Compiler Error a.cs(3,34): error CS1552: Array type specifier, [], must appear before parameter name

Array brackets [] can only be in one place. This is before the name of the array, not after. God alone knows why?!
a.cs class zzz { public static void Main() { int[] a = {1,2,3}; foreach (int in a) { } } } Compiler Error a.cs(6,14): error CS0230: Type and identifier are both required in a foreach statement

The foreach has a certain syntax and it lets you iterate over an object. Thus it requires the name of a variable that will contain the individual values of the collection object. We failed to give the int variable a name and hence got saddled with an error.

http://www.vijaymukhi.com/documents/books/csadv/chap1.htm (41 of 41)2/21/2010 7:37:58 PM

Você também pode gostar