DekGenius.com
[ Team LiB ] Previous Section Next Section

2.7 Variables and Parameters

A variable represents a typed storage location. A variable can be a local variable, parameter, array element, an instance field, or a static field.

All variables have an associated type, which essentially defines the possible values the variable can have and the operations that can be performed on that variable. C# is strongly typed, which means the set of operations that can be performed on a type are enforced at compile time, rather than at runtime. In addition, C# is type-safe, which ensures that a variable can be operated on only via the correct type with the help of runtime checking (except in unsafe blocks; see Section 4.8 in Chapter 4).

2.7.1 Definite Assignment

All variables in C# (except in unsafe contexts) must be assigned a value before they are used. A variable is either explicitly assigned a value or automatically assigned a default value. Automatic assignment occurs for static fields, class instance fields, and array elements not explicitly assigned a value. For example:

using System;
class Test {
  int v;
  // Constructors that initalize an instance of a Test
  public Test( ) {  } // v will be automatically assigned to 0
  public Test(int a) { // explicitly assign v a value
     v = a;
  }
  static void Main( ) {
    Test[ ] tests = new Test [2]; // declare array
    Console.WriteLine(tests[1]); // ok, elements assigned to null
    Test t;
    Console.WriteLine(t); // error, t not assigned before use
  }
}

2.7.2 Default Values

Essentially the default value for all primitive (or atomic) types is zero:

Type

Default value

Numeric types

0

Bool type

false

Char type

'\0'

Enum types

0

Reference type

null

The default value for each field in a complex (or composite) type is one of these aforementioned values.

2.7.3 Parameters

A method has a sequence of parameters. Parameters define the set of arguments that must be provided for that method. In this example the method Foo has a single parameter named p, of type int:

static void Foo(int p) {++p;}
static void Main( ) {
  Foo(8);
}
2.7.3.1 Passing arguments by value

By default, arguments in C# are passed by value, which is by far the most common case. This means a copy of the value is created when passed to the method:

static void Foo(int p) {++p;}
static void Main( ) {
  int x = 8;
  Foo(x); // make a copy of the value-type x
  Console.WriteLine(x); // x will still be 8
}

Assigning p a new value does not change the contents of x, since p and x reside in different memory locations.

2.7.3.2 Ref modifier

To pass by reference, C# provides a the parameter modifier ref, which allows p and x to refer to the same memory locations:

class Test {
  static void Foo(ref int p) {++p;}
  static void Main ( ) {
    int x = 8;
    Foo(ref x); // send reference of x to Foo
    Console.WriteLine(x); // x is now 9
  }
}

Now assigning p a new value changes the contents of x. This is usually the reason we want to pass by reference, though occasionally it is more efficient when passing large structs. Notice how the ref modifier and the method definition are required in the method call. This makes it very clear what's going on, and clears ambiguity since parameter modifiers change the signature of a method.

The ref modifier is essential when implementing a swap method:

class Test {
  static void Swap (ref string a, ref string b) {
    string temp = a;
    a = b;
    b = temp;
  }
  static void Main ( ) {
    string x = "Bush";
    string y = "Gore";
    Swap(ref x, ref y);
    System.Console.WriteLine("x is {0}, y is {1}", x, y);
  }
}
// outputs: x is Gore, y is Bush
2.7.3.3 The out modifier

C# is a language that enforces that variables are assigned before use, so it also provides the out modifier, which is the natural complement of the ref modifier. While a ref modifier requires that a variable is assigned a value before being passed to a method, the out modifier requires that a variable is assigned a value before returning from a method:

using System;
class Test {
  static void Split(string name, out string firstNames, 
                    out string lastName) {
     int i = name.LastIndexOf(' ');
     firstNames = name.Substring(0, i);
     lastName = name.Substring(i+1);
  }
  static void Main( ) {
    string a, b;
    Split("Nuno Bettencourt", out a, out b);
    Console.WriteLine("FirstName:{0}, LastName:{1}", a, b);
  }
}
2.7.3.4 The params modifier

The params parameter modifier may be specified on the last parameter of a method so that the method accepts any number of parameters of a particular type. For example:

using System;
class Test {
  static int Add(params int[ ] iarr) {
    int sum = 0;
    foreach(int i in iarr)
      sum += i;
    return sum;
  }
  static void Main( ) {
    int i = Add(1, 2, 3, 4);
    Console.WriteLine(i); // 10
  }
}
    [ Team LiB ] Previous Section Next Section