首页 > 开发 > 综合 > 正文

C#教程第五课:方法

2024-07-21 02:22:23
字体:
来源:转载
供稿:网友
本节课向你介绍c#的方法,其目的是:
1.了解方法的结构格式

2.了解静态和实例方法之间的区别

3.学会实例对象的使用

4.学会如何调用实例化的对象

5.学会方法的四种参数类型的使用

6.学会使用"this"引用

以往,对于每个程序来说,所有的工作都在main()方法中实现。这对于功能简单的程序是合适的,因为仅仅用来学习一些概念。有个更好的方法来组织你的程序,那就是使用方法。方法是很有用的,因为方法可以让你在不同的单元中分开设计你的逻辑模块。

方法的结构格式如下:

属性 修饰符 返回值类型 方法名(参数) { 语句 }

我们将在后面的课程中,讨论属性和修饰符。方法的返回值可以是任何一种c#的数据类型,该返回值可以赋给变量,以便在程序的后面部分使用。方法名是唯一,可以被程序调用。为使得你的代码变得更容易理解和记忆,方法的取名可以同所要进行的操作联系起来。你可以传递数据给方法,也可以从方法中返回数据。它们由大括号包围起来。大括号中的语句实现了方法的功能。

1.清单5-1. 一个简单的方法: onemethod.cs

using system;
class onemethod {
public static void main() {
string mychoice;
onemethod om = new onemethod();

do {
mychoice = om.getchoice();
// make a decision based on the user's choice
switch(mychoice) {
case "a":
case "a":
console.writeline("you wish to add an address.");
break;
case "d":
case "d":
console.writeline("you wish to delete an address.");
break;
case "m":
case "m":
console.writeline("you wish to modify an address.");
break;
case "v":
case "v":
console.writeline("you wish to view the address list.");
break;
case "q":
case "q":
console.writeline("bye.");
break;
default:
console.writeline("{0} is not a valid choice", mychoice);
}

// pause to allow the user to see the results
console.write("press any key to continue...");
console.readline();
console.writeline();
} while (mychoice != "q" && mychoice != "q"); // keep going until the user wants to quit
}

string getchoice() {
string mychoice;
// print a menu
console.writeline("my address book/n");
console.writeline("a - add new address");
console.writeline("d - delete address");
console.writeline("m - modify address");
console.writeline("v - view addresses");
console.writeline("q - quit/n");
console.writeline("choice (a,d,m,v,or q): ");

// retrieve the user's choice
mychoice = console.readline();
return mychoice;
}
}

说明

1.清单5-1中的程序类似于第四课中的doloop程序。

区别在于:前一课中的程序打印出菜单内容,并在main()方法中接受用户的输入,而本课中,该功能用一个名为getchoice()的方法实现,该方法的返回值类型是个字符串类型。在main方法中,在switch语句中用到了该串。方法"getchoice"实现了调用时所完成的工作。方法名后面的括号内是空的,因为调用getchoice()方法时,不需要传递任何数据。

2.在方法块中,我们首先定义了变量"mychoice"。

虽然它与 main()方法中的"mychoice"变量同名同类型, 但它们是不同的两个变量,因为局部变量仅仅在其定义的块内可见。换句话说, getchoice()方法中的"mychoice" 同main()方法中的"mychoice"变量没有丝毫联系。getchoice()方法打印出一个菜单到控制台,并读取用户的输入。"return" 语句把"mychoice"变量值返回给main()方法中的调用者getchoice()。注意: "return"语句返回类型同该方法中定义的返回值类型相同,本例中,该返回值是个字符串。

3.在main()方法中,在使用getchoice()之前,实例化了一个新的"onemethod"对象。

这是因为:我们没有指明一个"静态"修饰符。(注意:main()函数带有"静态"修饰符),getchoice()就成为一个实例的方法。 实例方法和静态方法的区别是:前者可以创建多个类的实例,每个实例有自己的单独的getchoice()方法。而一旦方法是静态的,就不存在方法的实例,你只能调用该静态方法的一个实现。

所以,正如前面所讲的,因为getchoice()并不是静态的,所以,我们必须实例化一个新对象来使用它。这是通过定义"onemethod om = new onemethod()"来进行的。在等号的左边,是对象引用"om",其类型是onemethod。"om"是个对象的引用,这点很重要,"om"并不是对象自身,它是个引用onemethod类型对象的变量。 在等号的右边,把新创建的onemethod对象赋给引用"om"。 关键字"new"是个在堆上创建对象的新实例的c#运算符。此处完成的工作是: 在堆上创建一个新的onemethod实例,并把它赋给om引用。一旦有了om引用的onemethod对象实例,就可以通过om引用来对实例进行处理。

方法,域和其他类成员可以通过"." (点)运算符进行访问,标识和操纵。一旦需要调用方法getchoice(),就通过om引用,并使用点运算符"om.getchoice()"来进行。 getchoice() 块中的语句执行完毕之后即返回。为了捕捉到getchoice()的返回值,我们使用了赋值运算符"="。 返回串放到了main()函数的局部变量 mychoice中,从那里,程序的其余部分按照前面课程中介绍的方式正常执行。

2.清单5-2. 方法参数:methodparams.cs

using system;
class address {
public string name;
public string address;
}
class methodparams {

public static void main() {
string mychoice;
methodparams mp = new methodparams();
do {
// show menu and get input from user
mychoice = mp.getchoice();
// make a decision based on the user's choice
mp.makedecision(mychoice);
// pause to allow the user to see the results
console.write("press any key to continue...");
console.readline();
console.writeline();
} while (mychoice != "q" && mychoice != "q"); // keep going until the user wants to quit
}

// show menu and get user's choice
string getchoice() {
string mychoice;
// print a menu
console.writeline("my address book/n");
console.writeline("a - add new address");
console.writeline("d - delete address");
console.writeline("m - modify address");
console.writeline("v - view addresses");
console.writeline("q - quit/n");
console.writeline("choice (a,d,m,v,or q): ");
// retrieve the user's choice
mychoice = console.readline();
return mychoice;
}

// make decision
void makedecision(string mychoice) {
address addr = new address();
switch(mychoice) {
case "a":
case "a":
addr.name = "joe";
addr.address = "c# station";
this.addaddress(ref addr);
break;
case "d":
case "d":
addr.name = "robert";
this.deleteaddress(addr.name);
break;
case "m":
case "m":
addr.name = "matt";
this.modifyaddress(out addr);
console.writeline("name is now {0}.", addr.name);
break;
case "v":
case "v":
this.viewaddresses("cheryl", "joe", "matt", "robert");
break;
case "q":
case "q":
console.writeline("bye.");
break;
default:
console.writeline("{0} is not a valid choice", mychoice);
}
}

// insert an address
void addaddress(ref address addr) {
console.writeline("name: {0}, address: {1} added.", addr.name, addr.address);
}
// remove an address
void deleteaddress(string name) {
console.writeline("you wish to delete {0}'s address.", name);
}
// change an address
void modifyaddress(out address addr) {
//console.writeline("name: {0}.", addr.name); // causes error!
addr = new address();
addr.name = "joe";
addr.address = "c# station";
}
// show addresses
void viewaddresses(params string[] names) {
foreach (string name in names) {
console.writeline("name: {0}", name);
}
}
}

说明

1.清单5-2是清单5-1的修改,主要是对程序进行了模块化,并添加了更多的实现,以便阐述参数传递的用法。

c#可以处理四种类型的参数:out(输出),ref(引用),params(数组)和value(值)。为了说明参数的用法,我们用两个字符串域创建地址类。

2.在main()方法中,我们调用getchoice()来读取用户的输入,并且把字符串放到mychoice变量中。

之后,把mychoice变量作为makedecision()函数的实在参数。在实现makedecision()方法时,注意其形式参数为字符串mychoice。需要再次说明的是:这是个新的mychoice变量,不同于调用者的实在参数,仅仅是适用于本方法的局部变量。 因为makedecision()方法的mychoice参数没有任何其他修饰符,故认为它是"值"参,即实在参数的值被拷贝到栈中,故作为值参的变量是局部的,任何对局部变量值的改变并不影响到调用者的实在参数的值。换句话说,值参仅仅是来自调用者的输入。

3.makedecision()方法中的switch语句完成如下功能:

在每种情形下,都调用相应的方法。这些方法的调用不同于main()方法。除了使用"mp" 引用,它们还使用了"this"关键字。"this"是对当前对象的引用。由于makedecision()方法不是静态方法,当前对象已经被实例化,所以可以使用"this"引用来调用同一实例中的方法。

4.addaddress()方法用到了"ref"参数,即引用可作为参数来传递,即该引用被拷贝到栈中,其引用的对象同调用者的实参所引用的对象是同一个。

这意味着:任何对局部引用的对象的改变也就是对调用者所引用的对象的改变。你可以想象一下,这就相当于输入/输出参数。

5.modifyaddress()中有一个输出参数。

输出参数仅仅传递给被调用函数。一旦调用该方法时,在栈中的仅有的一个引用未被赋值,因为根据赋值的确定性原则,在该变量没有被赋值之前,就不能使用该变量。modifyaddress()方法的第一行作为注释,说明了这一点。你可以试着去掉注释符,编译一下程序,看看结果如何。一旦该变量被赋了值,在程序返回之后,输出参数就被拷贝到调用者的参数中。所以,在方法返回之前,必须给输出参数赋值。

小结
c# 语言的一个很有用途的参数类型是数组参数,它须是一维或多维的数组。在makedecision()方法中,我们传递了用四个逗号隔开的字符串参数。参数的个数是变量。在viewaddresses()方法中,使用了foreach循环,逐一输出这些字符串。数组参数仅是一种输入性质的参数,任何对数组参数值的改变仅仅影响到局部的副本值。

概括地讲,你现在已经理解了方法的组织结构。你还了解了方法的实现可以采用的四种参数类型及其格式。 一旦你使用实例方法,就必须实例化该对象,静态方法则不同,后者可以在任何时候被调用。另外,你也了解了"this"引用是如何调用实例方法的。 
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表