3、买单!?还是我来吧!
小色:刚才咱们是说到了属性,在对象中还是可以调用方法的,这个你知道吗?
小力:知道啊,你刚才的lili.Cook()不就是在调用方法吗?
小色:没错,那方法的参数和返回值你知道怎么写吗?
小力:这个难不倒我,给你看看我写的基本结构对不对:
访问修饰符 返回值类型 方法名称(数据类型 参数1,数据类型 参数2……) { 方法体; return 返回值; } |
访问修饰符就是你刚给我讲的public、private那些,返回值类型必须和return的返回值类型相同,通过return关键字,可以将调用这个方法的地方接收到由方法回传的内容。方法名称就是给方法起的名字,在C#里用Pascal命名法来命名,要求每一个单词的首字母都大写,而参数就是要传递过来的值。对吧!?
小色:说的不错,那我现在来写一个简单的结账买单小程序,用方法来计算出来结果后将其输出:
class Pay {//支付类 public int Checkout() {//结账方法 int money = 0; money = 12 + 12 + 20 + 15 + 18; return money; } } class Program { static void {//程序主入口 int total = 173;//用来保存我这星期用来请客一共花的钱 int sum;//用来保存这次花的钱 Pay p = new Pay(); sum = p.Checkout();//调用并接收返回值 total += sum; Console.WriteLine("本次花销:{0},总共花销:{1}",sum,total); Console.ReadLine(); } } |
输出结果为:
本次花销:77,总共花销:250 |
小力:这就是一个没有参数但是有返回值的方法。通过方法的计算将返回值传递给调用它的地方,用sum来接收。这个程序很完美啊!
小色:如果程序仅仅写到这里的话应该是很完美,但是我现在改两次需求,看看你能不能改。第一次修改,我想让sum
传递到方法内,计算后再将其返回。
小力:当然可以了,只要修改代码为:
class Pay { public int Checkout(int sum) {//改动1 int money = 0; money = 12 + 12 + 20 + 15 + 18; sum = money;//改动2 return sum;//改动3 } } class Program { static void { int total = 173;//用来保存我这星期用来请客一共花的钱 int sum=0;//改动4 Pay p = new Pay(); sum = p.Checkout(sum);//改动5 total += sum; Console.WriteLine("本次花销:{0},总共花销:{1}",sum,total); Console.ReadLine(); } } |
小色:写的不错,由于sum变量属于局部变量,所以在Checkout方法中定义的sum和在Main方法中定义的sum互不影响。这样的话,确实没问题。第二次修改,我想让你将我的总共花销total也以参数的方式传递进去,并且在累加完之后也返回回来。
小力:这个根本不可能啊,方法的返回值必须与返回类型相同且唯一,你这样岂不是让我返回两个值吗?这个肯定是不行的。
小色:说是这么说,你有没有想过其他的方法呢?你看看我接下来的代码怎么样?
class Pay { public void Checkout(int sum,int total) { int money = 0; money = 12 + 12 + 20 + 15 + 18; sum = money; total = total + money; } } class Program { static void { int total = 173; int sum=0; Pay p = new Pay(); p.Checkout(sum,total); Console.WriteLine("本次花销:{0},总共花销:{1}",sum,total); Console.ReadLine(); } } |
小力:这个是没有返回值类型的方法,你是想将变量传递进方法里面,然后让方法修改,可是刚才也说过了这两个sum都是局部变量,total也如此啊,你这样最后的结果应该是这样才对:
本次花销:0,总共花销,173 |
小色:没错,也就是说我们其实只是传递了一个副本,而并没有在原本的基础上做修改,这种属于值传递,所以也肯定达不到我刚所提出的要求。但是C#早就给我们提供好了修改可以实现的方法,也就是使用ref关键字,使用这种关键字,就可以使得变量通过引用传递,修改原本的内容。要想使用ref,就必须在传递和接收的变量前都加上ref关键字,代码修改两个位置即可:
将public void Checkout(int sum,int total)改为public void Checkout(ref int sum,ref int total) |
将p.Checkout(sum,total);改为p.Checkout(ref sum,ref total); |
你会发现,结果就跟我们第一段代码执行出来的相同了。
小力:真的啊,看来C#真是个好东西,不仅可以通过值传递的方式来传递副本,还可以通过引用传递的方式来传递变量地址本身的内容。
小色:还没说完呢,先别急着总结。在刚才的代码中有一处写着int sum=0;想表达的意思是本次的消费是从0开始统计的。但是仔细想想,假如这顿饭里突然发现了一只黑飞机(苍蝇),然后你抓住经理脖领子要求全部免单并且赔偿损失。那这个初始值0不就一点意义都没有了吗。
小力:想想也是,这个sum变量就是想在方法里面得到结果而已,初始值一点用都没有,哪怕赋值一万也好,最后的结果还是本次的消费。我知道了,我们把初始值删掉不就行了。
小色:不行啊,删掉了VS就给我们报错了:使用了未赋值的局部变量
小力:快想想办法啊,照你这么说ref是一个侧重于修改的关键字,那有没有一个,不关心变量是否被初始化,主要侧重于输出的关键字啊?
小色:别急,有的!那就是out关键字了。你把上面sum前面的ref改为out,再试着将int sum=0;改为int sum;
(抢过我的电脑就开始改,看来女生急了也不淑女了……)
小力:搞定了!搞定了!看来真的可以
小色:ref作为引用参数必须在他们被传递给方法之前初始化,因为这是在传递一个已存在变量的引用,侧重于修改。out作为输出参数不需要在它被传递给方法之前初始化,因为方法在退出之前必须给输出参数赋值,侧重于输出。
小力:我这顿饭吃的还真是值了,这次还是我请吧,你要是累计上这次的饭,你就够二百五了。哈哈~~~
小色:是啊,也是巧了。你请吧,咱们去吃点冰激凌吧,一会我请。
(在她转身后,迅速让笔记本休眠后塞到后脑勺里。看来在大衣里面缝一个笔记本内胆还是有好处的。)
完稿日期:
(请看下回:是先有的蛋,还是先有的鸡?)