变量表示存储位置。每个变量都属于一种类型,它确定什么样的值可以存储在该变量中。局部变量是在方法、属性或索引器中声明的变量。局部变量是通过指定类型名称和声明符(它指定变量名和可选的初始值)定义的,如:
int a;
int b = 1;
但局部变量声明也可以包含多个声明符。a 和 b 的声明可以重写为:
int a, b = 1;
一个变量必须先赋值,然后才能使用它的值。示例
class Test
{
static void
int a;
int b = 1;
int c = a + b; // error, a not yet assigned
...
}
}
导致编译时错误,因为它试图在给变量 a 赋值之前使用它。
字段是与类或结构或与类或结构的实例关联的变量。用 static 修饰符声明的字段定义静态变量,不用此修饰符声明的字段则定义实例变量。静态字段与类型关联,而实例变量与实例关联。示例
using Personnel.Data;
class Employee
{
private static DataSet ds;
public string Name;
public decimal Salary;
...
}
显示了具有一个私有静态变量和两个公共实例变量的 Employee 类。
形参声明也定义变量。有四种类型的参数:值参数、引用参数、输出参数和参数数组。
值参用于“in”参数传递。在此过程中,自变量的值被传入方法中。因为一个值参在方法中用自己的变量存储(而非原自变量),所以对此参数的修改不会影响到原自变量。值参的变量是通过复制原自变量的值来初始化的。示例
using System;
class Test {
static void F(int p) {
Console.WriteLine("p = {0}", p);
p++;
}
static void Main() {
int a = 1;
Console.WriteLine("pre: a = {0}", a);
F(a);
Console.WriteLine("post: a = {0}", a);
}
}
显示了一个具有名为 p 的值参数的方法 F。示例输出结果如下
pre: a = 1
p = 1
post: a = 1
即使值参数 p 已修改。
“引用参数”用于“by reference”参数传递。在此过程中,“引用参数”就是调用者提供的自变量的别名。“引用参数”并不定义自己的变量,而是直接引用原自变量,因此对“引用参数”的修改就将直接影响相应原自变量的值。引用参数用 ref 修饰符来声明。示例
using System;
class Test {
static void Swap(ref int a, ref int b) {
int t = a;
a = b;
b = t;
}
static void Main() {
int x = 1;
int y = 2;
Console.WriteLine("pre: x = {0}, y = {1}", x, y);
Swap(ref x, ref y);
Console.WriteLine("post: x = {0}, y = {1}", x, y);
}
}
显示了一个具有两个引用参数的 Swap 方法。产生的输出为:
pre: x = 1, y = 2
post: x = 2, y = 1
在形参声明和形参的使用中都必须使用 ref 关键字。在调用位置使用 ref 可以引起对参数的特别注意,这样阅读代码的开发人员就会知道参数值可以因调用而更改。
对于输出参数来说,调用者提供的自变量的初始值并不重要,除此之外,输出参数与引用参数类似。输出参数是用 out 修饰符声明的。示例
using System;
class Test {
static void Divide(int a, int b, out int result, out int remainder) {
result = a / b;
remainder = a % b;
}
static void Main() {
for (int i = 1; i < 10; i++)
for (int j = 1; j < 10; j++) {
int ans, r;
Divide(i, j, out ans, out r);
Console.WriteLine("{0} / {1} = {2}r{3}", i, j, ans, r);
}
}
}
显示了一个 Divide 方法,该方法包含两个输出参数:一个参数用于除法的结果,另一个参数用于余数。
对于值、引用和输出这三种类型的参数,在调用方提供的自变量和用于表示它们的参数之间存在一对一的对应关系。参数数组则允许存在多对一关系:多个参数可以用一个自变量来表示。换言之,参数数组允许可变长度的自变量列表。
参数数组用 params 修饰符声明。一个给定的方法只能有一个参数数组,而且它必须始终是最后一个指定的参数。参数数组的类型总是一维数组类型。调用方可以传递一个属同一类型的数组变量,或任意多个与该数组的元素属同一类型的自变量。例如,示例
using System;
class Test
{
static void F(params int[] args) {
Console.WriteLine("# of arguments: {0}", args.Length);
for (int i = 0; i < args.Length; i++)
Console.WriteLine("\targs[{0}] = {1}", i, args[i]);
}
static void Main() {
F();
F(1);
F(1, 2);
F(1, 2, 3);
F(new int[] {1, 2, 3, 4});
}
}
显示了带数目可变的 int 参数的方法 F,以及对此方法的若干个调用。输出为:
# of arguments: 0
# of arguments: 1
args[0] = 1
# of arguments: 2
args[0] = 1
args[1] = 2
# of arguments: 3
args[0] = 1
args[1] = 2
args[2] = 3
# of arguments: 4
args[0] = 1
args[1] = 2
args[2] = 3
args[3] = 4
此介绍中出现的大部分示例使用 Console 类的 WriteLine 方法。此方法的参数替换行为(如下面的示例所示)
int a = 1, b = 2;
Console.WriteLine("a = {0}, b = {1}", a, b);
是使用参数数组完成的。为适应常见的各种需要,WriteLine 方法有若干个重载的方法供选用,这些方法中,有些需传递固定个数的参数,有些使用了参数数组。
namespace System
{
public class Console
{
public static void WriteLine(string s) {...}
public static void WriteLine(string s, object a) {...}
public static void WriteLine(string s, object a, object b) {...}
...
public static void WriteLine(string s, params object[] args) {...}
}
}