DekGenius.com
[ Team LiB ] Previous Section Next Section

2.3 Type Basics

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.

Functions

A function performs an action by executing a series of statements. For example, you may have a function that returns the distance between two points, or a function that calculates the average of an array of values. A function is a way of manipulating data.

Data

Data is values that functions operate on. For example, you may have data holding the coordinates of a point, or data holding an array of values. Data always has a particular type.

Types

A type has a set of data members and function members. The function members are used to manipulate the data members. The most common types are classes and structs, which provide a template for creating data; data is always an instance of a type.

Types are quite an abstract concept, so let's look at two concrete examples.

2.3.1 The String Class

The 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 Struct

The 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 -2n-1 to 2n-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 Type

You 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 Instances

Generally, 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 Conversions

Each 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.

    [ Team LiB ] Previous Section Next Section