1.3.5传递参数之值传递和引用传递

先把最重要的一句话放在前面:通常向方法传递一个实参时,对应的参数(形参)会用实参的一个副本来初始化。
1、(引用传递)首先是传递引用类型的参数:

  • 当我们将类型A定义为class类型时,则创建了一个引用类型。

  • 在main()函数中进行实例化后,调用ChangeA函数对A中的X进行修改,所得结果为:a1的值为:2,我们发现,调用ChangeA函数改变了a1的X值

  • 原因:调用函数ChangA传递参数a1,是传递的保存在栈中的内存地址,当改变X的值时改变的时堆中的值。堆中的值改变之后,所有的引用该地址的值都会发生改变,则会残生这种现象。

2、(值传递)其次是传递值类型的参数

  • 当我们将Class A改为Struct A时,A类型则变成了值类型
  • 在Main()函数中调用ChangeA进行改变A类型的X值,结果我们发现,X的值还是1:a1的值为:1,并没有改变。
  • 原因:在给函数传递参数时,会对实参赋值一个副本,导致函数改变的X值时存放在栈中的副本值,当我们打印a1.X值时栈中的值是没有改变的。
using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            var a1 = new A() { X = 1 };
            ChangeA(a1);
            Console.WriteLine($"a1的值为:{a1.X}");
            Console.ReadKey();
        }
        public static void ChangeA(A a)
        {
            a.X = 2;
        }
    }
    struct A
    {
        public int X { get; set; }

    }

}

3、(ref)如果我们想要在Struct中传递引用类型的值进行对值改变,我们怎么做呢?

  • 那就是使用我们ref关键字,对在函数中传递的实参进行
  • 需要改变的地方有两个:一个时函数声明时,在形参前加上ref关键字,另一个是在调用的时候也需要加上ref关键字。
  • ref关键字在实战中什么时候用的到欢迎评论(Thx)
using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            var a1 = new A() { X = 1 };
            ChangeA(ref a1);
            Console.WriteLine($"a1.X的值为:{a1.X}");
            Console.ReadKey();
        }
        public static void ChangeA(ref A a)
        {
            a.X = 2;
        }
    }
    struct A
    {
        public int X { get; set; }
    }
}

4、对引用的应用,类型于和C++的指针类似

  • 当我们使用ref关键字时,就会在函数调用时对实参创建一个引用,放在堆中,然后在函数中对堆中的数据进行处理
  • 如果我们在函数中对被创建的引用类型的参数进行操作的话,就相当于对C中的指针内容进行操作
  • 最后Main()函数输出的结果为a1.X的值为:3
public static void ChangeA(ref A a)
        {
            a.X = 2;
            a = new A { X = 3 };
        }

5、(out)如果我们想要从一个方法中返回一个数或者多个数据,并且这些数据的类型可能不同,那么我们有三种办法处理

  • 使用函数返回类型
  • 声明一个类或者结构用做返回类型
  • 使用out关键字,用于参数,将要返回的数据带出来
  • out关键字的使用会经常和Int.TryParse一起使用,Int.TryParse(int param1 ,out object param2)是用来判断param是否能转化为整数,如果能,则对param2进行赋值并返回。代码如下:
using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = Console.ReadLine();
            if (int.TryParse(input,out int result))
            {
                Console.WriteLine($"result:{result}");
            }
            else
            {
                Console.WriteLine("not a number");
            }
        }
    }
}

6、(in)如果我们想把一个参数传到方法内,并且保证该变量的值不被改变,我们可以使用in修饰符

  • 声明带in的函数时,将in放在参数类型的前面
  • 调用该函数时,使用或者不适用in都不会影响该函数的运行。
  • 使用带in修饰符的值类型不仅有助于确保不能更改内存,而且编译器还可以创建更好的优化代码。编译器可以使用引用代替方法调用复制值类型,从而减少所需的内存并提高性能。
using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
           
        }
        static void CantChange(in MyStruct myStruct)
        {
            myStruct.Data = 19;//编译出错,	该属性是只读的不能改变
        }
    }
    struct MyStruct
    {
        public int Data { get; set; }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值