A C# program is best understood in terms of three basic elements: functions, data, and types. This book assumes you have some programming experience, so let's start with a brief overview of functions and data (which you should have some familiarity with) and then move on to explain types in more detail.
Types are quite an abstract concept, so let's look at two concrete examples. 2.3.1 The String ClassThe string class specifies a sequence of characters . This means you can store values such as ".NET" or "http://oreilly.com". You can also perform functions such as returning the character at a particular position on the string or getting its lowercase representation. In this example, we output the lower case representation of ".NET" (which will be ".net"), and return the length of the string (which will be 4). To do this, we first create an instance of a string, then use the ToLower method and Length property, which are function members of that string. using System; class Test { static void Main ( ) { string s = ".NET"; Console.WriteLine (s.ToLower( )); // outputs ".net" Console.WriteLine (s.Length); // outputs 4 } } 2.3.2 The int StructThe int struct specifies a signed integer (a positive or negative whole number) that is 32 bits long. This means you can store values ranging from -2,147,483,648 to 2,147,483,647 (or -2 n-1 to 2 n-1 -1, in which n =32). With an int, you can perform functions such as adding, multiplying, etc. In this example, we output the result of multiplying 3 by 4. To do this, we create two instances of the int, and then use the * operator. The int type is actually a built-in type that supports primitive arithmetic functionality (such as * ), but it is helpful to think of the * operator as a function member of the int type. using System; class Example { static void Main ( ) { int a = 3; int b = 4; Console.WriteLine (a * b); } } 2.3.3 A Custom TypeYou can also define custom types in C#. In fact, a program is built by defining new types, each with a set of data members and function members. In this example, we build our own type, called Counter : // Imports types from System namespace, such as Console using System; class Counter { // New types are typically classes or structs // --- Data members --- int value; // field of type int int scaleFactor; // field of type int // Constructor, used to initialize a type instance public Counter(int scaleFactor) { this.scaleFactor = scaleFactor; } // Method public void Inc( ) { value+=scaleFactor; } // Property public int Count { get {return value; } } } class Test { // Execution begins here static void Main( ) { // Create an instance of counter type Counter c = new Counter(5); c.Inc( ); c.Inc( ); Console.WriteLine(c.Count); // prints "10"; // create another instance of counter type Counter d = new Counter(7); d.Inc( ); Console.WriteLine(d.Count); // prints "7"; } } 2.3.4 Type InstancesGenerally, you must create instances of a type to use that type. Data members and function members that require a type to be instantiated in order to be used are called instance members (by default, members are instance members). Data members and function members that can be used on the type itself are called static members. In this example, the instance method PrintName prints the name of a particular panda, while the static method PrintSpeciesName prints the name shared by all pandas in the application ( AppDomain ): using System; class Panda { string name; static string speciesName = "Ailuropoda melanoleuca"; // Initializes Panda(See Instance Constructors) public Panda(string n) { name = n; } public void PrintName( ) { Console.WriteLine(name); } public static void PrintSpeciesName( ) { Console.WriteLine(speciesName); } } class Test { static void Main( ) { Panda.PrintSpeciesName( ); // invoke static method Panda p1 = new Panda("Petey"); Panda p2 = new Panda("Jimmy"); p1.PrintName( ); // invoke instance method p2.PrintName( ); // invoke instance method } } Note that the invocation of static members from outside of their enclosing type requires specifying the type name. You may have deduced that Console 's WriteLine method is a static member. It is associated with the Console class, rather than an instance of the Console class. A function member should be static when it doesn't rely on any instance data members. Similarly, the Main method of all programs is a static member, which means that this method can be called without instantiating the enclosing class. 2.3.5 ConversionsEach type has its own set of rules defining how it can be converted to and from other types. Conversions between types may be implicit or explicit. Implicit conversions can be performed automatically, while explicit conversions require a cast: int x = 123456; // int is a 4-byte integer long y = x; // implicit conversion to 8-byte integer short z =(short)x // explicit conversion to 2-byte integer The rationale behind implicit conversions is they are guaranteed to succeed and do not lose information. Conversely, an explicit conversion is required either when runtime circumstances determine whether the conversion will succeed or whether information may be lost during the conversion. Most conversion rules are supplied by the language, such as the previously shown numeric conversions. Occasionally it is useful for developers to define their own implicit and explicit conversions, explained later in this chapter. |