C#值类型和引用类型的参数传递(ref,out)

C#中有两种类型,值类型,和引用类型。在内存中值类型是直接存储在内存的栈中的,引用类型在栈中存放一个地址,这个地址指向堆中的数据(引用类型的数据是存放在堆中的)

下面我们来看看两种类型参数传递有什么区别

先看一个例子

 /// <summary>
    ///
    /// 值类型的参数传递
    /// </summary>
    class ValueParms
    {
        public void Add(int a)
        {
            Console.WriteLine("Add:"+a);
        }
        
        public void Add1(ref int a)
        {
            a = a + 5;
            Console.WriteLine("Add1:"+a);
        }

        public void Add2(out int a)
        {
            a = 10;
            Console.WriteLine("Add2:"+a);
        }

    }

 class Program
    {   
        static void Main(string[] args)
        {

            int a=10;
            ValueParms valueParms = new ValueParms();

        /*@1*/    valueParms.Add(5); //5
        /*@2*/    Console.WriteLine("Main" + a);//10

    
         /*@3*/   valueParms.Add1(ref a);//15
         /*@4*/   Console.WriteLine("Main" + a);//15

       /*@5*/     valueParms.Add2(out a); //10
        /*@6*/    Console.WriteLine("Main" + a);//15

}

我们来看一下输出的结果,第一行输出为5,Main 方法里面的a= 10不会随着方法的结果而改变

第三行输出为15 ,第四行为什么也是15呢,是因为ref这个参数(实际是把a的地址给传进来了),会把方法里得到的结果(a=15)带给Main方法里的属性(实参)

第五行 参数out的意思是不接收外部的数据(把外部的地址传进来),在内部进行初始化,并把方法的结果返回带给实参

所以第五行和第六行都是 15;

out参数用的比较多,使用带out参数可以使我们避免大量使用try catch 语句

例子如下

string value = "ab";
            int num;
            //out传递也是变量的地址,内部给这个变量赋值
            if (int.TryParse(value, out num))//转换成功就返回true,并把结果存储在变量num中
            {
                Console.WriteLine("转换成功:" + num);
            }
            else {
                Console.WriteLine("转换失败");

            }

如果我们不加out这个参数,那就要使用try catch 语句 TryParse返回 true,false两个结果,用num去接收(相当于初始化)

并返回两个结果 转换成功,转换失败。

看完了值类型的传递我们来看引用类型的参数传递

 /// <summary>
    /// 引用类型的参数传递
    /// </summary>
    public class ClassParams
    {
        public void Say1(Person p)
        {
            Console.WriteLine("say1:1"+p.name); // fashi
            p = new Person();
            p.name = "xue";
            Console.WriteLine("say2:2"+p.name); //xue
        }

        public void Say2(ref Person p)
        {
            Console.WriteLine("say2:1"+p.name); //fashi
            p = new Person();
            p.name = "xue";
            Console.WriteLine("say2:2" + p.name); //xue
        }
        
        public void Say3(out Person p)
        {
            p = new Person();
            p.name = "xue";
            Console.WriteLine("say3:"+p.name);//xue
        }
    }

    public class Person
    {
        public string name;

    }

static void Main (String []args)

{

ClassParams p2 = new ClassParams();

            Person p = new Person();
            p.name = "fashi";

            p2.Say1(p);

            Console.WriteLine("Main" + p.name); //fashi

            p2.Say2(ref p);

            Console.WriteLine("Main" + p.name); //xue


            p2.Say3(out p);
            Console.WriteLine("Main" + p.name);//xue

}

  方法里面的输出都很容易理解,我们来讲一下Main方法里的输出,第一调用没有参数传递的引用类型,Main里面输出fashi

第二种带参数的ref 为什么输出的是xue,因为调用带ref参数的方法把  p指向的xue的地址赋值给了p指向fashi的地址,所以Main里面输出的是fashi

第三种带参数的out的不接收方法里的参数,并把自己的初始化的地址赋值给了p指向的fashi的地址,所以Main里面输出的是xue

我们现在来总结一下

 *ref,out:传递值类型的变量的地址;

 * ref:传递过程中保留初始值;
 * out:传递过程中不保留初始值;
 * ref:一般需要把外部的值传入到方法中使用并进行修改;
 * out:一般传递变量进入某个方法中接收数据;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值