c# 值类型和引用类型,值传递和引用传递

值类型和引用类型


在c#内置基本类型当中,除了object和string外,都是引用类型。同时,自己定义的类,也都是引用类型。因为自定义类全部继承自System.Object。

更多参见:.net中6个重要的基础概念:Stack, heap, Value types, reference types, boxing and Unboxing.

值传递和引用传递


创建控制台程序文件:ValueAndReference.cs

c# 值类型和引用类型,值传递和引用传递 Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSType
{
    
public class ValueAndReference
    {
        
public ValueAndReference()
        {
            TestClass tc 
= new TestClass();
            ChangeValue(tc.ps);
//值传递
            Console.WriteLine("tc.ps value:" + tc.ps);
            
//output : 绯红女郎,哎呀哎呀! 

            ChangeValue( 
ref tc.ps);//使用ref关键来强制为引用传递
            Console.WriteLine("ref tc.ps value:" + tc.ps);
            
//output : 绯红女郎,哎呀哎呀! was Changed

            ChangeObject(tc);
//类默认为引用传递
            Console.WriteLine(" tc.ps value:" + tc.ps);
            
//output: Hello world

            
string s = "海盗船长,嘿咻嘿咻";
            ChangeValue(s);
//值传递
            Console.WriteLine("s value:" + s);
            
//output: 海盗船长,嘿咻嘿咻

            ChangeValue(
ref s);//使用ref关键来强制为引用传递
            Console.WriteLine("s value:" + s);
            
//output: 海盗船长,嘿咻嘿咻 was Changed

            Console.ReadLine();
        }

        
public void ChangeValue( string s)
        {
            s 
= s + " was Changed";
        }

        
public void ChangeValue(ref string s)
        {
            s 
= s + " was Changed";
        }

        
public void ChangeObject(TestClass o)
        {
            o.ps 
= "Hello world";
        }
    }

    
public class TestClass
    {
        
public string ps = "绯红女郎,哎呀哎呀!";
        
public TestClass()
        {

        }
    }
}



我们来分析一下:

1.类TestClass是辅助类,是辅助我们测试的

2.类ValueAndReference里面有3个方法,两个:ChangeValue和一个ChangeObject,方法名字无所谓,你可以写个ChangeObject123,ChangeObjectsdfsdf来用。

3.C#里面的值类型变量进行传递时,全部是值传递。

c#里面的引用类型变量进行传递时,全部是引用传递。但是string例外。比如:

    string s = "海盗船长,嘿咻嘿咻";
            ChangeValue(s);//值传递
            Console.WriteLine("s value:" + s);
            //output: 海盗船长,嘿咻嘿咻

这里的变量s本来是引用类型,但是传递时是作为值传递。


4. 值传递:

    string s = "海盗船长,嘿咻嘿咻";
            ChangeValue(s);//值传递
            Console.WriteLine("s value:" + s);
            //output: 海盗船长,嘿咻嘿咻

s变量的作用域不在ChangeValue方法内部。我们使用参数的方式把s传递进去,注意这里传递的是s变量的值。不是s变量在内存里面的地址。等于把s变量copy了一份传递给ChangeValue.虽然,s变量的值在ChangeValue内部被改变了,但是ChangeValue(s)无法改变外部s变量的值。

5.引用传递:

    ChangeValue(ref s);//使用ref关键来强制为引用传递
            Console.WriteLine("s value:" + s);

这个时候,就是把s变量在内存里面的地址传递过去了,不是值的copy.因此,我们当我们把这个内存地址所指向的值修改后,外部的s变量的值也就被修改了。因为方法内外的s变量是一个内存地址,指向同一个值。

===========================

通俗例子:

假如我有100¥(外部s变量),现在我给你100¥(传递s变量),但是我不是直接给你,而是把我手里的100复制一下,然后给你100(传递的方式:值传递),你去买东西后,还剩40(ChangeValue(string s)函数的功能),但是我的100还是没变(外部s变量的值没变化)。


再来,我有100¥,在钱包里放着(外部s变量)。我把放钱包的地方告诉你,你直接去钱包里面拿100¥(传递方式:引用传递,就是传内存地址),你去买东西后,还剩40,然后你把剩余的钱放回钱包(ChangeValue(ref string s)函数的功能),我的钱也只有40¥了(外部s变量的值被改变了)

你可能感兴趣的:(引用传递)