第六章 函数

定义一个函数

void型函数:
void <函数名>(参数表)
{
}

其他类型函数:
<类型名> <函数名>(参数表)
{
return <返回值>;  //返回值类型要和函数的类型一致
}

例:

{
            string myFuction(int a)
           {
               if(a==1)
               {
                   return "One";
               }
               else
               {
                   return "Other";
               }
           }
} 

 

参数


----------------------------------------
值类型与引用类型的区别
----------------------------------------
* 变量根据存储方式的不同,可以分为:值类型和引用类型,它们之间的区别:
* 值类型在内存的一个地方(堆栈)存储它们自己和它们的内容
* 引用类型在内存的一个地方(堆)存储一个引用,而在另外一个地方存储内容。
* 还用引用类型可以为null,而值类型总是包含一个值,
* 简单类型中的string和object是引用类型,数组也是隐式的引用类型。我们创建的每个类也是引用类型。
*/

/*
无论对于值类型还是引用类型,对其作为函数参数或者返回值的时候,都是容易犯错的地方,要加以注意,如下:
对于值类型来说,当其作为函数参数时,一般直接操作时不能被修改的
public void Increment( int i )
{
 i++;
}
  要想在函数中对传进去的参数做真正的修改,需要借助于ref这个关键字,如下
pubic void increment( ref int i )
{
i++;
}

也就是说在函数中对值类型参数进行修改,必须使用ref或者out关键字.
而对于引用类型来说,当其作为函数参数的时候,情况恰恰相反,即不希望在函数中被修改,如下:
public void AddValue( MyType typValue )
{
 typValue.Count = typValue.Count + 15;
}
由于对于引用类型来说,其赋值操作只是对原有对象的引用,对其进行修改 就是对原有对象的修改,这是很多情况都部希望发生的.
为了防止这种事的发生,需要给引用类型提供clone函数.clone函数用法比较复杂,以后会单独去研究一下.我们还是重点关注本
例中ref和out关键字的区别和用法吧.

----------------------------------------
ref与out的区别及用法,params关键字的用法.
----------------------------------------
ref和out都是C#中的关键字,所实现的功能也差不多,都是指定一个参数按照引用传递。对于编译后的程序而言,它们之间没有任何区别,也就是说它们只有语法区别。总结起来,他们有如下语法区别:

1、ref传进去的参数必须在调用前初始化,out不必,即:
int i;
SomeMethod( ref i );//语法错误
SomeMethod( out i );//通过

2、ref传进去的参数在函数内部可以直接使用,而out不可:
public void SomeMethod(ref int i)
{
int j=i;//通过
//...
}
public void SomeMethod(out int i)
{
int j=i;//语法错误
}

3、ref传进去的参数在函数内部可以不被修改,但out必须在离开函数体前进行赋值。

总结:
应该说,系统对ref的限制是更少一些的。out虽然不要求在调用前一定要初始化,但是其值在函数内部是不可见的,也就是不能使用通过out传进来的值,并且一定要赋一个值。也就是说函数承担初始化这个变量的责任
两者都是按地址传递的,使用后都将改变原来的数值。
其次:rel可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所以你必须初始化一次。这个就是两个的区别,或者说就像有的网友说的,rel是有进有出,out是只出不入.

params 是数组型参数,根据实参形式选择引用传递或值传递,包含数量可变的参数。特别注意:使用Params参数要检验参数是否为null
使用params 关键字指定的参数必须是函数定义中最后一个参数.

*/
示例:

using System;
using System.Collections.Generic;
using System.Text;
 
 
namespace testParameterApp
{
    /// <summary>
    /// Class1 的摘要说明。
    /// </summary>
    class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            // TODO: 在此处添加代码以启动应用程序
            //
            //声明整形变量,都未初始化
            int num1, num2, sum1, sum2, sum3;
            //用作out引用变量,无需初始化,num1,num2都没有被赋值
            SetValue(out num1, 10);
            SetValue(out num2, 5);
            Console.WriteLine("Number1={0},Number2={1}", num1, num2);
            //用作reg引用变量,需要初始化,num1和num2在经过setvalue处理已经被赋值了。
            AddOne(ref num1);
            Console.WriteLine("Number1={0},Number2={1}", num1, num2);
            //num1-num2再赋值给num1,num2值不变
            Subtract(ref num1, num2);
            Console.WriteLine("Number1={0},Number2={1}", num1, num2);
            //params参数可以为0个或多个
            //sum1=0
            sum1 = GetSum();
            //sum1=6+5=11
            sum1 = GetSum(num1, num2);
            //sum2为out引用,无需初始化
            //sum2=6+5=11
            GetSum(out sum2, num1, num2);
            /*下面的语句等同于:
             * int [] intarry = new int[]{num1,num2};
            sum3 = GetArraySum(intarry);*/
            sum3 = GetArraySum(new int[] { num1, num2 });
            Console.WriteLine("Sum1={0},Sum2={1},Sum3={2}", sum1, sum2, sum3);
            Console.ReadLine();
        }
        //i传引用,实参值将在方法中改变
        public static void AddOne(ref int i)
        {
            Console.WriteLine("ref参数");
            i = i + 1;
        }
 
        //i传引用,实参值将改变,j传值,实参值不变
        public static void Subtract(ref int i, int j)
        {
            Console.WriteLine("ref参数 and val参数");
            i = i - j;
            j = j - 1; //j值在方法中修改,不影响实参
        }
 
        //i值out引用,实参值等于方法中i运算结果
        public static void SetValue(out int i, int j)
        {
            Console.WriteLine("out参数 and val参数");
            //因为参数i使用out关键字,在离开参数之前一定要进行赋值,num1=10,num2=5
            i = j;
        }
 
        //iArray表示多个int型参数,传值
        //参数中使用params关键字,则该函数的参数个数是可变的,利于函数的重载。
        public static int GetSum(params int[] iArray)
        {
            Console.WriteLine("params参数");
            int sum = 0;
            //使用foreach语句遍历各个参数
            foreach (int i in iArray)
            {
                sum = sum + i;
            }
            return (sum);
        }
        //sum为out引用参数,iArray表示多个int型值参数 
        //GetSum的重载
        public static void GetSum(out int sum, params int[] iArray)
        {
            Console.WriteLine("out参数 and params参数");
            //out参数在方法中必须先初始化,才可使用
            sum = 0;
            //使用for循环遍历参数,通过iArray[i]访问各个参数
            for (int i = 0; i < iArray.Length; i++)
            {
                sum = sum + iArray[i];
            }
        }
        //数组int[]为值参数
        public static int GetArraySum(int[] iArray)
        {
            int sum = 0;
            foreach (int i in iArray)
            {
                sum += i;
            }
            return sum;
        }
    }
}
 

 

 

递归调用

public static int Foo(int i)

{

if (i <= 0) return 0;

// 小于0 的返回0

else if(i > 0 && i <= 2) return 1;

// 前两位数都是1

else return Foo(i -1) + Foo(i - 2);

//从第三位数开始 等于前两位的和,如果i-1位数是第一位或者第二位数就返回1 如果不是继续返回为前两位的和一直到是1为止,然后依次将其后的一个数算出来,最终算到你设置的地方 第30个数字。
//调用这个方法运算到这的时候如果需要递归,就再次调用自己,其实最初调用的方法就一直停在了 else return Foo(i -1) + Foo(i - 2); 这个位置,新调用的方法也是这么算 如果到了这里else return Foo(i -1) + Foo(i - 2); 也是停在这继续再调用这个方法,知道不再调用了,再一步步的返回一个值,直到第一次调用的地方,就把要的值求出来了
//递归嘛,可以看做第一次到这就停了,这个数再用这个方法去算,一层层的算下去直到出来数字1就是这个方法到不了这,而是直接返回一个数的时候,在一层层的倒退算回去,最终就算到你第一次调用的时候了,也就是30的时候
}
i30=i29+i28 i29=i28+i27 i28=i27+i26 i28=i27+i26 i27=i26+i25 i27=i26+i25 i26=i25+i24 .... ..... ...... i3=i2+i1=1+1=2 ......

 

 

变量的作用域

简单的理解为,变量的作用域其实就是作用在包括变量的花括号和嵌套在其中的花括号里

转载于:https://www.cnblogs.com/griff/archive/2009/11/08/1598688.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值