函数
在C#中,函数是一种方法,可提供在应用程序中的任何一处执行的代码块
定义和使用函数
函数定义:
1 两个关键字:static和void
2 函数名后跟圆括号,如Write()
3 一个要执行的代码块,放在花括号中
例如:
static void Main(string[] args)
{
...
}
static关键字与面向对象的概念相关
void关键字表明函数没有返回值
注意:在定义函数和调用函数时,必须使用圆括号
返回值
当函数返回一个值时,需要:
1 在函数声明中指定返回值的类型代替关键字void
2 使用return关键字结束函数的执行,把返回值传送给调用代码
语法:
static <returnType> <functionName>()
{
...
return <returnValue>;
}
<returnType>可以是任何类型
<returnValue>必须是一个值,其类型可以是<returnType>,也可以隐式转换为该类型
return语句必须在函数的闭合花括号 } 之前处理
注意:return可以用在通过void关键字声明的函数中(没有返回值),用于跳出函数,但不能设置<returnValue>
参数
当函数接受参数时,需要:
1 函数在其定义中指定接受的参数列表,以及这些参数的类型
2 在每个函数调用中匹配的参数列表
语法:
static <returnType> <functionName>(<paramType> <paramName>, ...)
{
...
return <returnValue>;
}
其中可以有任意多个参数,每个参数都有一个类型和一个名称。参数用逗号分隔开。
每个参数都在函数的代码中用作一个变量。
1 参数匹配
在调用函数时,必须使参数与函数定义中指定的参数完全匹配,包括参数的类型、个数和顺序。不过可以用“重载函数”来解决。
2 参数数组
C#允许为函数指定一个(只能指定一个)特定的参数,这个参数必须是函数定义中的最后一个参数,称为参数数组。参数数组可以使用个数不定的参数调用函数,它可以使用params关键字来定义。
语法:
static <returnType> <functionName>(<p1Type> <p1Name>, ... , params <type>[] <name>)
{
...
return <returnValue>;
}
调用函数:
<functionName>(<p1>, ... , <val1>, <val2>, ...)
其中<val1>, <val2>等都是类型为<type>的值,用于初始化<name>数组。
参数个数没有限制(没有也可以),但类型都必须是<type>。
参数数组特别适合为在处理过程中要使用的函数指定其他信息
3 引用参数和值参数
使用ref关键字指定参数,可以通过引用传递参数
引用传递参数,即函数处理的变量与函数调用中使用的变量相同,对这个变量进行的任何改变都会影响用作参数的变量值
例如:
static void showDouble(ref int val)
{
val *= 2;
}
函数调用:
int myNumber = 5;
showDouble(ref myNumber);
Console.WriteLine("myNumber = {0}", myNumber);
结果:
myNumber = 10
限制:
指定引用的参数必须是变量(由于参数值可能会改变,不能使用常量)
必须使用初始化过的变量
4 输出参数
使用out关键字,指定所给的参数是一个输出参数
out关键字的使用方式与ref关键字相同,执行方式与引用参数完全一样,即在函数执行完毕后,该参数的值将返回给函数调用中使用的变量
区别:
可以把未赋值的变量用作out参数
out参数会看作是还未赋值,而且必须在函数里初始化,即参数原来的值将会丢失
如果每次调用时,参数都要进行初始化的话应该使用out参数
变量的作用域
给定的变量有一个作用域,访问该变量要通过这个作用域来实现。
变量的作用域包含定义它们的代码块和直接嵌套在其中的代码块
局部变量:作用域覆盖一个函数的变量
全局变量:作用域可覆盖多个函数
全局变量必须用static或const关键字,来定义这种形式的全局变量
如果要修改全局变量的值,就需要使用static,因为const禁止修改变量的值。
局部变量和全局变量同名,全局变量就会被屏蔽
例如:
static int num;
static void showNum()
{
num = 5;
}
protected void Button1_Click(object sender, EventArgs e)
{
num = 2;
showNum();
Label1.Text = num.ToString();//5
}
protected void Button2_Click(object sender, EventArgs e)
{
int num = 2;
showDouble();
Label1.Text = num.ToString();//2
}
其他结构中变量的作用域
变量的作用域包含定义它们的代码块和直接嵌套在其中的代码块。这也可以应用到其他代码块上,例如分支和循环结构的代码块。
一般情况下,最好在声明和初始化所有的变量后,再在代码块中使用它们
不过对于for循环的循环变量,一般不会在外部使用,通常把它声明为循环块的一部分
参数和返回值与全局数据
可以通过全局数据以及参数和返回值,与函数交换数据
使用全局数据存储能减少在函数调用中犯错的可能性,但使代码更难理解
一般情况下,最好使用参数,而不使用全局数据,但使用这个技术并没有错。
Main()函数
Main()是C#应用程序的入口点,执行这个函数就是执行应用程序。
函数有一个参数string[] args
Main函数声明方式:
static void Main()
static void Main(string[] args)
static int Main()
static int Main(string[] args)
上面的第三、四个版本返回一个int值,它们可以用于表示应用程序如何终止,通常用作一种错误提示(但这不是强制的),一般情况下,返回0反映了“正常”的终止(即应用程序执行完毕,并安全地终止)。
Main()的参数args是从应用程序的外部接受信息的方法,这些信息在运行期间指定,其形式是命令行参数。
在执行控制台应用程序时,指定的任何命令行参数都放在这个args数组中,接着可以根据需要在应用程序中使用这些参数。
使用args参数与使用其他字符串数组类似。我们没有对参数进行任何异样的操作,只是把指定的信息写到屏幕上。
注意,每个参数都用空格分隔开,如果参数包含空格,就可以用双引号把参数括起来,这样才不会把这个参数解释为多个参数。
结构函数
结构类型可在一个地方存储多个数据元素,结构可以包含函数和数据
例如:
结构类型
struct customerName
{
public string firstName, lastName;
// 结构函数
public string Name ()
{
return firstName + " " + lastName;
}
}
使用:
customerName myCustomer;
myCustomer.firstName = "John";
myCustomer.lastName = "Franklin";
Console.WriteLine(mycustomer.Name());
注意,Name()函数可以直接访问firstName 和 lastName结构成员,在customerName结构中,它们可以看作是全局成员。
函数的重载
函数重载允许创建同名的多个函数,这些函数可使用不同的参数类型。
注意:用相同的名称和参数定义两个函数是错误的
在重载函数时,应包括参数的所有方面,包括类型、数目、关键字(如ref、out)等
委托
委托是一种可以把引用存储为函数的类型
委托的声明
使用delegate关键字:
delegate <returnType> <delegatename>(<type1> <param1>, ...);
把变量初始化为与委托有相同签名的函数引用
使用委托变量调用函数:
<delegatename> process = new <delegatename>(<functionname>);
<type1> p1 = val;
<returnType> nVal = process(p1);
例如:
static int show1(int n)
{
return n*2;
}
delegate int delegatename(int n);
protected void Button1_Click(object sender, EventArgs e)
{
delegatename process = new delegatename(show1);
Label1.Text = process(3).ToString();
Label2.Text = executeFunction(process).ToString();
}
// 还可以通过参数把委托传递给一个函数
static int executeFunction(delegatename process)
{
return process(5);
}