C# 参数1:值参数----值类型和引用类型及特例string

本文详细讲解了C#中值参数和引用参数的传递方式。值参数在方法调用时会创建副本,不会影响原始值。而引用参数则分为两种情况:一是方法内创建新实例,此时在堆上分配新内存,不影响原实例;二是未创建新实例,修改会直接影响原实例。此外,还特别讨论了string类型的特殊情况,因其不可变性,每次赋值都会在堆上创建新对象。
摘要由CSDN通过智能技术生成
using System;

namespace ConsoleIdeaTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //A.值参数传递
            int x = 100;
            Calculator.Calculate(x);  //120
            Console.WriteLine("主函数中:\n哈希代码:{0}\n变量的值:{1}\n", x.GetHashCode(), x); //100;传值参数是复制x的副本到方法中操作,输出的x的值不会影响主函数中x的值
            Console.WriteLine("==========================");

            //B.引用参数传递并在方法1中为引用创建新实例(少见)
            Student stu = new Student() { Name = "Jerry" }; //先在主函数中创建了引用变量stu和实例new student
            Anmethod1(stu);
            Console.WriteLine("主函数中:\n哈希代码:{0}\n变量的值:{1}\n", stu.Name.GetHashCode(), stu.Name);
            Console.WriteLine("==========================");
            //观察可以发现传引用参数的时候打印出的Name不一样;但即使一样,也可以根据不同的哈希代码来确定这是两个不同的对象
            //传引用参数,在将变量传入方法后,新创建了实例,内存上就又给新实例在堆上分配了一块新区域;

            //C.引用参数传递但未在方法2中新建实例
            Anmethod2(stu);
            Console.WriteLine("主函数中:\nStu哈希代码:{0}\nStu变量的值:{1}\n", stu.Name.GetHashCode(), stu.Name);

        }

        static void Anmethod1(Student stu)
        {
            //B.传递引用参数调用的方法1
            stu = new Student() { Name = "Tom" }; //引用变量stu传入方法后,重新创建了一个新的实例new student
            Console.WriteLine("方法1中:\n哈希代码:{0}\n变量的值:{1}\n", stu.Name.GetHashCode(),stu.Name);
        }
        static void Anmethod2(Student stu)
        {
            //C.传递引用参数调用的方法2
            stu.Name = "Tom";     //引用变量stu传入方法后,相当于在栈上创建了一个新的引用变量,也指向主函数中的同一个实例
            Console.WriteLine("方法2中:\n哈希代码:{0}\n变量的值:{1}\n", stu.Name.GetHashCode(), stu.Name);
        }
    }


    class Calculator
    {
        public static void Calculate(int x)
        {
            //A.传值参数调用的方法
            x = x + 20;
            Console.WriteLine("方法中:\n哈希代码:{0}\n变量的值:{1}\n", x.GetHashCode(), x);
        }
    }

    class Student
    {
        //给类添加的属性,用来让上方主函数的实例可以访问Name属性
        public string  Name { get; set; }
    }
}

一、值参数:

        1、值类型:

        值类型的值参数,方法调用时在栈上创建副本,方法内计算修改的均为该副本,不会影响原本栈上的值参数。

        2、引用类型

        引用类型的值参数,分以下两种情况:

        ①:引用类型的值参数在方法内新建了实例。这种情况下系统先给方法内的引用类型值参数在栈上分配内存空间,然后再给新实例在堆上分配新的内存空间,该引用类型的值参数会指向新实例在堆上的内存地址,后续的修改均为对新实例修改,不影响原引用类型值参数和对应的实例;

        ②:引用类型的值参数在方法内未新建实例。这种情况下系统先给方法内的引用类型值参数在栈上分配内存空间,然后引用类型值参数指向原实例在堆内存中的地址,后续的修改会直接改变原实例的值(两个小朋友拉着同一个气球)。

        3、特例string

        string本身是引用类型,但字符串具有不可变性

        不可变性:当你给一个字符串重新赋值之后,老值并没有在内存中销毁,而是重新开辟一块空间存储新值。

        当引用变量的值的类型是string时,如果后续要为该实例赋予新的字符串值,内存会在堆上为新值开辟空间,而不是直接覆盖旧值(所以如果短时间内大量重复为同一实例赋不同的字符串值,容易浪费内存);同时,相同字符串值的实例,他们的引用变量指向同一个该字符串的内存地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值