3、买单!?还是我来吧!

小色:刚才咱们是说到了属性,在对象中还是可以调用方法的,这个你知道吗?

小力:知道啊,你刚才的lili.Cook()不就是在调用方法吗?

小色:没错,那方法的参数和返回值你知道怎么写吗?

小力:这个难不倒我,给你看看我写的基本结构对不对:

访问修饰符  返回值类型  方法名称(数据类型 参数1,数据类型 参数2……)

{

方法体;

return 返回值;

}

1.3.1

访问修饰符就是你刚给我讲的publicprivate那些,返回值类型必须和return的返回值类型相同,通过return关键字,可以将调用这个方法的地方接收到由方法回传的内容。方法名称就是给方法起的名字,在C#里用Pascal命名法来命名,要求每一个单词的首字母都大写,而参数就是要传递过来的值。对吧!?

 小色:说的不错,那我现在来写一个简单的结账买单小程序,用方法来计算出来结果后将其输出: 

    class Pay

    {//支付类

        public int Checkout()

        {//结账方法

            int money = 0;

            money = 12 + 12 + 20 + 15 + 18;

            return money;

        }

}

class Program

    {

        static void Main(string[] args)

        {//程序主入口

            int total = 173;//用来保存我这星期用来请客一共花的钱

            int sum;//用来保存这次花的钱

            Pay p = new Pay();

            sum = p.Checkout();//调用并接收返回值

            total += sum;

            Console.WriteLine("本次花销:{0},总共花销:{1}",sum,total);

            Console.ReadLine();

        }

 }

1.3.2

输出结果为:

本次花销: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 Main(string[] args)

        {  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();

        }

}

1.3.3

小色:写的不错,由于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 Main(string[] args)

      {    int total = 173;

            int sum=0;

            Pay p = new Pay();

            p.Checkout(sum,total);

            Console.WriteLine("本次花销:{0},总共花销:{1}",sum,total);

            Console.ReadLine();

}

}

1.3.4

小力:这个是没有返回值类型的方法,你是想将变量传递进方法里面,然后让方法修改,可是刚才也说过了这两个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);

1.3.5

你会发现,结果就跟我们第一段代码执行出来的相同了。

小力:真的啊,看来C#真是个好东西,不仅可以通过值传递的方式来传递副本,还可以通过引用传递的方式来传递变量地址本身的内容。

小色:还没说完呢,先别急着总结。在刚才的代码中有一处写着int sum=0;想表达的意思是本次的消费是从0开始统计的。但是仔细想想,假如这顿饭里突然发现了一只黑飞机(苍蝇),然后你抓住经理脖领子要求全部免单并且赔偿损失。那这个初始值0不就一点意义都没有了吗。

小力:想想也是,这个sum变量就是想在方法里面得到结果而已,初始值一点用都没有,哪怕赋值一万也好,最后的结果还是本次的消费。我知道了,我们把初始值删掉不就行了。

小色:不行啊,删掉了VS就给我们报错了:使用了未赋值的局部变量

小力:快想想办法啊,照你这么说ref是一个侧重于修改的关键字,那有没有一个,不关心变量是否被初始化,主要侧重于输出的关键字啊?

小色:别急,有的!那就是out关键字了。你把上面sum前面的ref改为out,再试着将int sum=0;改为int sum;

(抢过我的电脑就开始改,看来女生急了也不淑女了……)

       小力:搞定了!搞定了!看来真的可以

小色:ref作为引用参数必须在他们被传递给方法之前初始化,因为这是在传递一个已存在变量的引用,侧重于修改。out作为输出参数不需要在它被传递给方法之前初始化,因为方法在退出之前必须给输出参数赋值,侧重于输出。

小力:我这顿饭吃的还真是值了,这次还是我请吧,你要是累计上这次的饭,你就够二百五了。哈哈~~~

小色:是啊,也是巧了。你请吧,咱们去吃点冰激凌吧,一会我请。

(在她转身后,迅速让笔记本休眠后塞到后脑勺里。看来在大衣里面缝一个笔记本内胆还是有好处的。)

 

完稿日期:2009115  1830

(请看下回:是先有的蛋,还是先有的鸡?